diff --git a/src/Numerics/Complex.cs b/src/Numerics/Complex.cs
index 71ebd61b..51d3a9b1 100644
--- a/src/Numerics/Complex.cs
+++ b/src/Numerics/Complex.cs
@@ -1279,7 +1279,17 @@ namespace MathNet.Numerics
#region Conversion
///
- /// Explicit conversion of a real decimal to a real Complex.
+ /// 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.
@@ -1289,7 +1299,7 @@ namespace MathNet.Numerics
}
///
- /// Implicit conversion of a real byte to a real Complex.
+ /// Implicit conversion of a real byte to a Complex.
///
/// The byte value to convert.
/// The result of the conversion.
@@ -1299,7 +1309,7 @@ namespace MathNet.Numerics
}
///
- /// Implicit conversion of a real short to a real Complex.
+ /// Implicit conversion of a real short to a Complex.
///
/// The short value to convert.
/// The result of the conversion.
@@ -1309,7 +1319,7 @@ namespace MathNet.Numerics
}
///
- /// Implicit conversion of a real int to a real Complex.
+ /// Implicit conversion of a real int to a Complex.
///
/// The int value to convert.
/// The result of the conversion.
@@ -1319,7 +1329,7 @@ namespace MathNet.Numerics
}
///
- /// Implicit conversion of a real long to a real Complex.
+ /// Implicit conversion of a real long to a Complex.
///
/// The long value to convert.
/// The result of the conversion.
@@ -1329,7 +1339,7 @@ namespace MathNet.Numerics
}
///
- /// Implicit conversion of a real uint to a real Complex.
+ /// Implicit conversion of a real uint to a Complex.
///
/// The uint value to convert.
/// The result of the conversion.
@@ -1339,7 +1349,7 @@ namespace MathNet.Numerics
}
///
- /// Implicit conversion of a real ulong to a real Complex.
+ /// Implicit conversion of a real ulong to a Complex.
///
/// The ulong value to convert.
/// The result of the conversion.
@@ -1349,7 +1359,7 @@ namespace MathNet.Numerics
}
///
- /// Implicit conversion of a real float to a real Complex.
+ /// Implicit conversion of a real float to a Complex.
///
/// The float value to convert.
/// The result of the conversion.
@@ -1359,7 +1369,7 @@ namespace MathNet.Numerics
}
///
- /// Implicit conversion of a real double to a real Complex.
+ /// Implicit conversion of a real double to a Complex.
///
/// The double value to convert.
/// The result of the conversion.
diff --git a/src/Numerics/Complex32.cs b/src/Numerics/Complex32.cs
new file mode 100644
index 00000000..0afdb618
--- /dev/null
+++ b/src/Numerics/Complex32.cs
@@ -0,0 +1,1383 @@
+//
+// 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;
+
+ ///
+ /// 32-bit Complex32 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 such
+ /// as , ...
+ /// are also provided. Note that the Complex32 structures
+ /// has two special constant values and
+ /// .
+ ///
+ ///
+ /// In order to avoid possible ambiguities resulting from a
+ /// Complex32(float, float) constructor, the static methods
+ /// and
+ /// are provided instead.
+ ///
+ ///
+ ///
+ /// Complex32 x = Complex32.FromRealImaginary(1d, 2d);
+ /// Complex32 y = Complex32.FromModulusArgument(1d, 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)]
+ public struct Complex32 : IFormattable, IEquatable, IPrecisionSupport
+ {
+ #region fields
+
+ ///
+ /// Represents imaginary unit number.
+ ///
+ private static readonly Complex32 _i = new Complex32(0, 1);
+
+ ///
+ /// Represents a infinite complex number
+ ///
+ private static readonly Complex32 _infinity = new Complex32(float.PositiveInfinity, float.PositiveInfinity);
+
+ ///
+ /// Represents not-a-number.
+ ///
+ private static readonly Complex32 _nan = new Complex32(float.NaN, float.NaN);
+
+ ///
+ /// Representing the one value.
+ ///
+ private static readonly Complex32 _one = new Complex32(1.0f, 0.0f);
+
+ ///
+ /// Representing the zero value.
+ ///
+ private static readonly Complex32 _zero = new Complex32(0.0f, 0.0f);
+
+ ///
+ /// The real component of the complex number.
+ ///
+ private readonly float _real;
+
+ ///
+ /// The imaginary component of the complex number.
+ ///
+ private readonly float _imag;
+
+ #endregion fields
+
+ #region Constructor
+
+ ///
+ /// 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.
+ ///
+ public Complex32(float real, float 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 Complex32 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 Complex32 Infinity
+ {
+ get { return _infinity; }
+ }
+
+ ///
+ /// Gets a value representing not-a-number. This field is constant.
+ ///
+ /// A value representing not-a-number.
+ public static Complex32 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 Complex32 ImaginaryOne
+ {
+ get { return _i; }
+ }
+
+ ///
+ /// Gets a value representing the zero value. This field is constant.
+ ///
+ /// A value representing the zero value.
+ public static Complex32 Zero
+ {
+ get { return new Complex32(0.0f, 0.0f); }
+ }
+
+ ///
+ /// Gets a value representing the 1 value. This field is constant.
+ ///
+ /// A value representing the 1 value.
+ public static Complex32 One
+ {
+ get { return _one; }
+ }
+
+ #endregion Properties
+
+ ///
+ /// Gets the real component of the complex number.
+ ///
+ /// The real component of the complex number.
+ public float Real
+ {
+ get { return _real; }
+ }
+
+ ///
+ /// Gets the real imaginary component of the complex number.
+ ///
+ /// The real imaginary component of the complex number.
+ public float Imaginary
+ {
+ get { return _imag; }
+ }
+
+ ///
+ /// Gets a value indicating whether the Complex32 is zero.
+ ///
+ /// true if this instance is zero; otherwise, false.
+ public bool IsZero
+ {
+ get { 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
+ {
+ get { 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
+ {
+ get { 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
+ {
+ get { 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
+ {
+ get { 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
+ {
+ get { 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
+ {
+ get { return _imag == 0.0f && _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 Complex32 Conjugate
+ {
+ get { return new Complex32(_real, -_imag); }
+ }
+
+ ///
+ /// Gets the magnitude or modulus of this Complex32.
+ ///
+ ///
+ public float Magnitude
+ {
+ get { return (float)Math.Sqrt((_real * _real) + (_imag * _imag)); }
+ }
+
+ ///
+ /// Gets the squared magnitude of this Complex32.
+ ///
+ ///
+ public float MagnitudeSquared
+ {
+ get { return (_real * _real) + (_imag * _imag); }
+ }
+
+ ///
+ /// Gets 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.
+ ///
+ public float Phase
+ {
+ get
+ {
+ if (IsReal && _real < 0)
+ {
+ return (float)Math.PI;
+ }
+
+ return IsRealNonNegative ? 0.0f : (float)Math.Atan2(_imag, _real);
+ }
+ }
+
+ ///
+ /// Gets the unity of this complex (same argument, but on the unit circle; exp(I*arg))
+ ///
+ 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((float)(_real / mod), (float)(_imag / mod));
+ }
+ }
+
+ #region Exponential Functions
+
+ ///
+ /// 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)Trig.Cosine(_imag), exp * (float)Trig.Sine(_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);
+ }
+
+ ///
+ /// 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 > 0.0f)
+ {
+ return Zero;
+ }
+
+ if (exponent.Real < 0)
+ {
+ if (exponent.Imaginary == 0.0f)
+ {
+ return new Complex32(float.PositiveInfinity, 0.0f);
+ }
+
+ return 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;
+ }
+
+ #endregion
+
+ #region Static Initializers
+
+ ///
+ /// Constructs a Complex32 from its real
+ /// and imaginary parts.
+ ///
+ ///
+ /// The value for the real component.
+ ///
+ ///
+ /// The value for the imaginary component.
+ ///
+ ///
+ /// A new Complex32 with the given values.
+ ///
+ public static Complex32 WithRealImaginary(float real, float imaginary)
+ {
+ return new Complex32(real, imaginary);
+ }
+
+ ///
+ /// Constructs a Complex32 from its modulus and
+ /// argument.
+ ///
+ ///
+ /// Must be non-negative.
+ ///
+ ///
+ /// Real number.
+ ///
+ ///
+ /// A new Complex32 from the given values.
+ ///
+ public static Complex32 WithModulusArgument(float modulus, float argument)
+ {
+ if (modulus < 0.0f)
+ {
+ throw new ArgumentOutOfRangeException("modulus", modulus, Resources.ArgumentNotNegative);
+ }
+
+ return new Complex32(modulus * (float)Math.Cos(argument), modulus * (float)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.0f)
+ {
+ ret.Append(_real.ToString(format, formatProvider));
+ }
+
+ if (_imag != 0.0f)
+ {
+ if (_real != 0.0f)
+ {
+ if (_imag < 0)
+ {
+ ret.Append(" ");
+ }
+ else
+ {
+ ret.Append(" + ");
+ }
+ }
+
+ ret.Append(_imag.ToString(format, formatProvider)).Append("i");
+ }
+
+ if (ret.Length == 0)
+ {
+ ret.Append(0.0f.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(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()
+ {
+ 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 Complex32) && Equals((Complex32)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 ==(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.
+ /// The result of the division.
+ /// The dividend.
+ /// The divisor.
+ public static Complex32 operator /(Complex32 dividend, Complex32 divisor)
+ {
+ if (divisor.IsZero)
+ {
+ return Infinity;
+ }
+
+ var modSquared = divisor.MagnitudeSquared;
+ return new Complex32(
+ ((dividend._real * divisor._real) + (dividend._imag * divisor._imag)) / modSquared,
+ ((dividend._imag * divisor._real) - (dividend._real * divisor._imag)) / modSquared);
+ }
+
+ /// Division operator. Divides a float value by a complex number.
+ /// The result of the division.
+ /// The dividend.
+ /// The divisor.
+ public static Complex32 operator /(float dividend, Complex32 divisor)
+ {
+ if (divisor.IsZero)
+ {
+ return Infinity;
+ }
+
+ var zmod = divisor.MagnitudeSquared;
+ return new Complex32(dividend * divisor._real / zmod, -dividend * divisor._imag / zmod);
+ }
+
+ /// 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 (divisor == 0.0f)
+ {
+ return Infinity;
+ }
+
+ return new Complex32(dividend._real / divisor, dividend._imag / divisor);
+ }
+
+ ///
+ /// Unary addition.
+ ///
+ ///
+ /// Returns the same complex number.
+ ///
+ public Complex32 Plus()
+ {
+ return this;
+ }
+
+ ///
+ /// Unary minus.
+ ///
+ ///
+ /// The negated value of this complex number.
+ ///
+ public Complex32 Negate()
+ {
+ return -this;
+ }
+
+ ///
+ /// Adds a complex number to this one.
+ ///
+ ///
+ /// The result of the addition.
+ ///
+ ///
+ /// The other complex number to add.
+ ///
+ public Complex32 Add(Complex32 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 Complex32 Subtract(Complex32 other)
+ {
+ return this - other;
+ }
+
+ ///
+ /// Multiplies this complex number with this one.
+ ///
+ ///
+ /// The result of the multiplication.
+ ///
+ ///
+ /// The complex number to multiply.
+ ///
+ public Complex32 Multiply(Complex32 multiplier)
+ {
+ return this * multiplier;
+ }
+
+ ///
+ /// Divides this complex number by another.
+ ///
+ ///
+ /// The result of the division.
+ ///
+ ///
+ /// The divisor.
+ ///
+ public Complex32 Divide(Complex32 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(Complex32 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 float.
+ ///
+ ///
+ /// A complex number containing the value specified by the given string.
+ ///
+ ///
+ /// The string to parse.
+ ///
+ public static Complex32 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 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)
+ {
+ 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;
+ 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();
+ }
+ }
+
+ 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;
+ }
+ }
+
+ var value = GlobalizationHelper.ParseSingle(ref token, format.GetCultureInfo());
+
+ // 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 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 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.
+ 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.
+ 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);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/Numerics/GlobalizationHelper.cs b/src/Numerics/GlobalizationHelper.cs
index e619d709..3f01362c 100644
--- a/src/Numerics/GlobalizationHelper.cs
+++ b/src/Numerics/GlobalizationHelper.cs
@@ -158,5 +158,39 @@ namespace MathNet.Numerics
token = token.Next;
return value;
}
+
+ ///
+ /// Globalized Parsing: Parse a float number
+ ///
+ /// First token of the number.
+ /// Culture Info.
+ /// The parsed float number using the given culture information.
+ ///
+ internal static float ParseSingle(ref LinkedListNode token, CultureInfo culture)
+ {
+ // in case the + and - in scientific notation are separated, join them back together.
+ if (token.Value.EndsWith("e", true, culture))
+ {
+ if (token.Next == null || token.Next.Next == null)
+ {
+ throw new FormatException();
+ }
+
+ token.Value = token.Value + token.Next.Value + token.Next.Next.Value;
+
+ var list = token.List;
+ list.Remove(token.Next.Next);
+ list.Remove(token.Next);
+ }
+
+ float value;
+ if (!Single.TryParse(token.Value, NumberStyles.Any, culture, out value))
+ {
+ throw new FormatException();
+ }
+
+ token = token.Next;
+ return value;
+ }
}
}
\ No newline at end of file
diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj
index 25f1d94f..d9810795 100644
--- a/src/Numerics/Numerics.csproj
+++ b/src/Numerics/Numerics.csproj
@@ -72,6 +72,7 @@
+
diff --git a/src/Numerics/Precision.cs b/src/Numerics/Precision.cs
index 3e2c6726..7af2db1d 100644
--- a/src/Numerics/Precision.cs
+++ b/src/Numerics/Precision.cs
@@ -95,7 +95,10 @@ namespace MathNet.Numerics
private static readonly int _numberOfDecimalPlacesForFloats;
/// Value representing 10 * 2^(-52)
- private static readonly double _defaultRelativeAccuracy = _doubleMachinePrecision * 10;
+ private static readonly double _defaultDoubleRelativeAccuracy = _doubleMachinePrecision * 10;
+
+ /// Value representing 10 * 2^(-52)
+ private static readonly float _defaultSingleRelativeAccuracy = (float)(_singleMachinePrecision * 10);
#endregion
@@ -691,7 +694,19 @@ namespace MathNet.Numerics
public static bool AlmostEqual(this double a, double b)
{
double diff = a - b;
- return AlmostEqualWithError(a, b, diff, _defaultRelativeAccuracy);
+ return AlmostEqualWithError(a, b, diff, _defaultDoubleRelativeAccuracy);
+ }
+
+ ///
+ /// Checks whether two real numbers are almost equal.
+ ///
+ /// The first number
+ /// The second number
+ /// true if the two values differ by no more than 10 * 2^(-52); false otherwise.
+ public static bool AlmostEqual(this float a, float b)
+ {
+ double diff = a - b;
+ return AlmostEqualWithError(a, b, diff, _defaultSingleRelativeAccuracy);
}
///
@@ -705,7 +720,7 @@ namespace MathNet.Numerics
where T : IPrecisionSupport
{
double diff = a.NormOfDifference(b);
- return AlmostEqualWithError(a.Norm(), b.Norm(), diff, _defaultRelativeAccuracy);
+ return AlmostEqualWithError(a.Norm(), b.Norm(), diff, _defaultDoubleRelativeAccuracy);
}
///
@@ -995,6 +1010,62 @@ namespace MathNet.Numerics
return AlmostEqualWithRelativeDecimalPlaces(a, b, decimalPlaces);
}
+ ///
+ /// Compares two floats and determines if they are equal to within the specified number of decimal places or not. If the numbers
+ /// are very close to zero an absolute difference is compared, otherwise the relative difference is compared.
+ ///
+ ///
+ ///
+ /// The values are equal if the difference between the two numbers is smaller than 10^(-numberOfDecimalPlaces). We divide by
+ /// two so that we have half the range on each side of the numbers, e.g. if == 2, then 0.01 will equal between
+ /// 0.005 and 0.015, but not 0.02 and not 0.00
+ ///
+ ///
+ /// The first value.
+ /// The second value.
+ /// The number of decimal places.
+ /// if both doubles are equal to each other within the specified number of decimal places; otherwise .
+ ///
+ /// Thrown if is smaller than zero.
+ ///
+ public static bool AlmostEqualInDecimalPlaces(this float a, float b, int decimalPlaces)
+ {
+ if (decimalPlaces <= 0)
+ {
+ // Can't have a negative number of decimal places
+ throw new ArgumentOutOfRangeException("decimalPlaces");
+ }
+
+ // If A or B are a NAN, return false. NANs are equal to nothing,
+ // not even themselves.
+ if (double.IsNaN(a) || double.IsNaN(b))
+ {
+ return false;
+ }
+
+ // If A or B are infinity (positive or negative) then
+ // only return true if they are exactly equal to each other -
+ // that is, if they are both infinities of the same sign.
+ if (double.IsInfinity(a) || double.IsInfinity(b))
+ {
+ return a == b;
+ }
+
+ if (Math.Abs(a) < _doubleMachinePrecision || Math.Abs(b) < _doubleMachinePrecision)
+ {
+ return AlmostEqualWithAbsoluteDecimalPlaces(a, b, decimalPlaces);
+ }
+
+ // If both numbers are equal, get out now. This should remove the possibility of both numbers being zero
+ // and any problems associated with that.
+ if (a.Equals(b))
+ {
+ return true;
+ }
+
+ return AlmostEqualWithRelativeDecimalPlaces(a, b, decimalPlaces);
+ }
+
///
/// Compares two doubles and determines if they are equal to within the specified number of decimal places or not.
///
diff --git a/src/UnitTests/AssertHelpers.cs b/src/UnitTests/AssertHelpers.cs
index 05f5b971..4088d5eb 100644
--- a/src/UnitTests/AssertHelpers.cs
+++ b/src/UnitTests/AssertHelpers.cs
@@ -80,6 +80,28 @@ namespace MathNet.Numerics.UnitTests
}
}
+
+ ///
+ /// Asserts that the expected value and the actual value are equal up to a certain number of decimal places.
+ ///
+ /// The expected value.
+ /// The actual value.
+ /// The number of decimal places to agree on.
+ public static void AlmostEqual(Complex32 expected, Complex32 actual, int decimalPlaces)
+ {
+ bool pass = expected.Real.AlmostEqualInDecimalPlaces(actual.Real, decimalPlaces);
+ if (!pass)
+ {
+ Assert.Fail("Real components are not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected.Real, actual.Real);
+ }
+
+ pass = expected.Imaginary.AlmostEqualInDecimalPlaces(actual.Imaginary, decimalPlaces);
+ if (!pass)
+ {
+ Assert.Fail("Imaginary components are not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected.Imaginary, actual.Imaginary);
+ }
+ }
+
///
/// Asserts that the expected value and the actual value are equal up to a certain
/// maximum error.
diff --git a/src/UnitTests/ComplexTests/Complex32Test.TextHandling.cs b/src/UnitTests/ComplexTests/Complex32Test.TextHandling.cs
new file mode 100644
index 00000000..f6f168b8
--- /dev/null
+++ b/src/UnitTests/ComplexTests/Complex32Test.TextHandling.cs
@@ -0,0 +1,284 @@
+//
+// 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.UnitTests.ComplexTests
+{
+ using System;
+ using System.Globalization;
+ using MbUnit.Framework;
+
+ [TestFixture]
+ public class Complex32TextHandlingTest
+ {
+ [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(float real, float imag, string expected)
+ {
+ var numberFormat = NumberFormatInfo.CurrentInfo;
+ var a = new Complex32(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, Complex32.NaN.ToString(provider));
+ Assert.AreEqual(infinity, Complex32.Infinity.ToString(provider));
+ Assert.AreEqual("0", Complex32.Zero.ToString(provider));
+ Assert.AreEqual(String.Format("{0}", number), new Complex32(1.1f, 0.0f).ToString(provider));
+ Assert.AreEqual(String.Format("-{0}", number), new Complex32(-1.1f, 0f).ToString(provider));
+ Assert.AreEqual(String.Format("-{0}i", number), new Complex32(0.0f, -1.1f).ToString(provider));
+ Assert.AreEqual(String.Format("{0}i", number), new Complex32(0.0f, 1.1f).ToString(provider));
+ Assert.AreEqual(String.Format("{0} + {0}i", number), new Complex32(1.1f, 1.1f).ToString(provider));
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanFormatComplexToStringWithFormat()
+ {
+ Assert.AreEqual("0", String.Format("{0:G}", Complex32.Zero));
+ Assert.AreEqual("1 + 2i", String.Format("{0:G}", new Complex32(1, 2)));
+ Assert.AreEqual("001 + 002i", String.Format("{0:000;minus 000;zero}", new Complex32(1, 2)));
+ Assert.AreEqual("minus 002i", String.Format("{0:000;minus 000;zero}", new Complex32(0, -2)));
+ Assert.AreEqual("zero", String.Format("{0:000;minus 000;zero}", Complex32.Zero));
+
+ Assert.AreEqual("0", Complex32.Zero.ToString("G"));
+ Assert.AreEqual("1 + 2i", new Complex32(1, 2).ToString("G"));
+ Assert.AreEqual("001 + 002i", new Complex32(1, 2).ToString("#000;minus 000;zero"));
+ Assert.AreEqual("minus 002i", new Complex32(0, -2).ToString("#000;minus 000;zero"));
+ Assert.AreEqual("zero", Complex32.Zero.ToString("#000;minus 000;zero"));
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanFormatComplexToStringWithFormatInvariant()
+ {
+ var culture = CultureInfo.InvariantCulture;
+
+ Assert.AreEqual("NaN", String.Format(culture, "{0:.000}", Complex32.NaN));
+ Assert.AreEqual(".000", String.Format(culture, "{0:.000}", Complex32.Zero));
+ Assert.AreEqual("1.100", String.Format(culture, "{0:.000}", new Complex32(1.1f, 0.0f)));
+ Assert.AreEqual("1.100 + 1.100i", String.Format(culture, "{0:.000}", new Complex32(1.1f, 1.1f)));
+
+ Assert.AreEqual("NaN", Complex32.NaN.ToString("#.000", culture));
+ Assert.AreEqual("Infinity", Complex32.Infinity.ToString("#.000", culture));
+ Assert.AreEqual(".000", Complex32.Zero.ToString("#.000", culture));
+ Assert.AreEqual("1.100", new Complex32(1.1f, 0.0f).ToString("#.000", culture));
+ Assert.AreEqual("-1.100i", new Complex32(0.0f, -1.1f).ToString("#.000", culture));
+ Assert.AreEqual("1.100i", new Complex32(0.0f, 1.1f).ToString("#.000", culture));
+ Assert.AreEqual("1.100 + 1.100i", new Complex32(1.1f, 1.1f).ToString("#.000", culture));
+ }
+
+ [Test]
+ [Row("-1 -2i", -1, -2, "en-US")]
+ [Row("-1 - 2i ", -1, -2, "de-CH")]
+ public void CanParseStringToComplexWithCulture(
+ string text, float expectedReal, float expectedImaginary, string cultureName)
+ {
+ Complex32 parsed = Complex32.Parse(text, CultureInfo.GetCultureInfo(cultureName));
+ Assert.AreEqual(expectedReal, parsed.Real);
+ Assert.AreEqual(expectedImaginary, parsed.Imaginary);
+ }
+
+ [Test]
+ [Row("1", 1, 0)]
+ [Row("-1", -1, 0)]
+ [Row("-i", 0, -1)]
+ [Row("i", 0, 1)]
+ [Row("2i", 0, 2)]
+ [Row("1 + 2i", 1, 2)]
+ [Row("1+2i", 1, 2)]
+ [Row("1 - 2i", 1, -2)]
+ [Row("1-2i", 1, -2)]
+ [Row("1,2 ", 1, 2)]
+ [Row("1 , 2", 1, 2)]
+ [Row("1,2i", 1, 2)]
+ [Row("-1, -2i", -1, -2)]
+ [Row(" - 1 , - 2 i ", -1, -2)]
+ [Row("(+1,2i)", 1, 2)]
+ [Row("(-1 , -2)", -1, -2)]
+ [Row("(-1 , -2i)", -1, -2)]
+ [Row("(+1e1 , -2e-2i)", 10, -0.02)]
+ [Row("(-1E1 -2e2i)", -10, -200)]
+ [Row("(-1e+1 -2e2i)", -10, -200)]
+ [Row("(-1e1 -2e+2i)", -10, -200)]
+ [Row("(-1e-1 -2E2i)", -0.1, -200)]
+ [Row("(-1e1 -2e-2i)", -10, -0.02)]
+ [Row("(-1E+1 -2e+2i)", -10, -200)]
+ [Row("(-1e-1,-2e-2i)", -0.1, -0.02)]
+ [Row("(+1 +2i)", 1, 2)]
+ [Row("(-1E+1 -2e+2i)", -10, -200)]
+ [Row("(-1e-1,-2e-2i)", -0.1, -0.02)]
+ public void CanTryParseStringToComplexWithInvariant(string str, float expectedReal, float expectedImaginary)
+ {
+ var invariantCulture = CultureInfo.InvariantCulture;
+ Complex32 z;
+ var ret = Complex32.TryParse(str, invariantCulture, out z);
+ Assert.IsTrue(ret);
+ Assert.AreEqual(expectedReal, z.Real);
+ Assert.AreEqual(expectedImaginary, z.Imaginary);
+ }
+
+ [Test]
+ public void ParseThrowsFormatExceptionIfMissingClosingParen()
+ {
+ Assert.Throws(() => Complex32.Parse("(1,2"));
+ }
+
+ [Test]
+ public void TryParseCanHandleSymbols()
+ {
+ Complex32 z;
+ var ni = NumberFormatInfo.CurrentInfo;
+ var separator = CultureInfo.CurrentCulture.TextInfo.ListSeparator;
+ var ret = Complex32.TryParse(
+ ni.NegativeInfinitySymbol + separator + ni.PositiveInfinitySymbol, out z);
+ Assert.IsTrue(ret, "A1");
+ Assert.AreEqual(float.NegativeInfinity, z.Real, "A2");
+ Assert.AreEqual(float.PositiveInfinity, z.Imaginary, "A3");
+
+ ret = Complex32.TryParse(ni.NaNSymbol + separator + ni.NaNSymbol, out z);
+ Assert.IsTrue(ret, "B1");
+ Assert.AreEqual(float.NaN, z.Real, "B2");
+ Assert.AreEqual(float.NaN, z.Imaginary, "B3");
+
+ ret = Complex32.TryParse(ni.NegativeInfinitySymbol + "+" + ni.PositiveInfinitySymbol + "i", out z);
+ Assert.IsTrue(ret, "C1");
+ Assert.AreEqual(float.NegativeInfinity, z.Real, "C2");
+ Assert.AreEqual(float.PositiveInfinity, z.Imaginary, "C3");
+
+ ret = Complex32.TryParse(ni.NaNSymbol + "+" + ni.NaNSymbol + "i", out z);
+ Assert.IsTrue(ret, "D1");
+ Assert.AreEqual(float.NaN, z.Real, "D2");
+ Assert.AreEqual(float.NaN, z.Imaginary, "D3");
+
+ ret = Complex32.TryParse(
+ float.MaxValue.ToString("R") + " " + float.MinValue.ToString("R") + "i",
+ out z);
+ Assert.IsTrue(ret, "E1");
+ Assert.AreEqual(float.MaxValue, z.Real, "E2");
+ Assert.AreEqual(float.MinValue, z.Imaginary, "E3");
+ }
+
+ [Test]
+ [Row("en-US")]
+ [Row("tr-TR")]
+ [Row("de-DE")]
+ [Row("de-CH")]
+ [Row("he-IL")]
+ public void TryParseCanHandleSymbolsWithCulture(string cultureName)
+ {
+ Complex32 z;
+ var culture = CultureInfo.GetCultureInfo(cultureName);
+ var ni = culture.NumberFormat;
+ var separator = culture.TextInfo.ListSeparator;
+ var ret = Complex32.TryParse(
+ ni.NegativeInfinitySymbol + separator + ni.PositiveInfinitySymbol, culture, out z);
+ Assert.IsTrue(ret, "A1");
+ Assert.AreEqual(float.NegativeInfinity, z.Real, "A2");
+ Assert.AreEqual(float.PositiveInfinity, z.Imaginary, "A3");
+
+ ret = Complex32.TryParse(ni.NaNSymbol + separator + ni.NaNSymbol, culture, out z);
+ Assert.IsTrue(ret, "B1");
+ Assert.AreEqual(float.NaN, z.Real, "B2");
+ Assert.AreEqual(float.NaN, z.Imaginary, "B3");
+
+ ret = Complex32.TryParse(ni.NegativeInfinitySymbol + "+" + ni.PositiveInfinitySymbol + "i", culture, out z);
+ Assert.IsTrue(ret, "C1");
+ Assert.AreEqual(float.NegativeInfinity, z.Real, "C2");
+ Assert.AreEqual(float.PositiveInfinity, z.Imaginary, "C3");
+
+ ret = Complex32.TryParse(ni.NaNSymbol + "+" + ni.NaNSymbol + "i", culture, out z);
+ Assert.IsTrue(ret, "D1");
+ Assert.AreEqual(float.NaN, z.Real, "D2");
+ Assert.AreEqual(float.NaN, z.Imaginary, "D3");
+
+ ret = Complex32.TryParse(
+ float.MaxValue.ToString("R", culture) + " " + float.MinValue.ToString("R", culture) + "i",
+ culture,
+ out z);
+ Assert.IsTrue(ret, "E1");
+ Assert.AreEqual(float.MaxValue, z.Real, "E2");
+ Assert.AreEqual(float.MinValue, z.Imaginary, "E3");
+ }
+
+ [Test]
+ [Row("")]
+ [Row("+")]
+ [Row("1-")]
+ [Row("i+")]
+ [Row("1/2i")]
+ [Row("1i+2i")]
+ [Row("i1i")]
+ [Row("(1i,2)")]
+ [Row("1e+")]
+ [Row("1e")]
+ [Row("1,")]
+ [Row(",1")]
+ [Row(null)]
+ [Row("()")]
+ [Row("( )")]
+ public void TryParseReturnsFalseWhenGivenBadValueWithInvariant(string str)
+ {
+ Complex32 z;
+ var ret = Complex32.TryParse(str, CultureInfo.InvariantCulture, out z);
+ Assert.IsFalse(ret);
+ Assert.AreEqual(0, z.Real);
+ Assert.AreEqual(0, z.Imaginary);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/UnitTests/ComplexTests/Complex32Test.cs b/src/UnitTests/ComplexTests/Complex32Test.cs
new file mode 100644
index 00000000..2ad39642
--- /dev/null
+++ b/src/UnitTests/ComplexTests/Complex32Test.cs
@@ -0,0 +1,572 @@
+//
+// 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.UnitTests.ComplexTests
+{
+ using System;
+ using MbUnit.Framework;
+
+ [TestFixture]
+ public class Complex32Test
+ {
+ [Test]
+ [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.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)));
+ AssertEx.That(() => -2.2f + new Complex32(-1.1f, 2.2f) == new Complex32(-3.3f, 2.2f));
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanAddSubtractComplexNumbersUsingOperartor()
+ {
+ 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);
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanAddTwoComplexNumbers()
+ {
+ 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);
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanAddTwoComplexNumbersUsingOperartor()
+ {
+ 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);
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanCalculateHashCode()
+ {
+ var complex = new Complex32(1, 0);
+ Assert.AreEqual(1065353216, complex.GetHashCode());
+ complex = new Complex32(0, 1);
+ Assert.AreEqual(-1065353216, complex.GetHashCode());
+ complex = new Complex32(1, 1);
+ Assert.AreEqual(-16777216, complex.GetHashCode());
+ }
+
+ [Test]
+ [Row(0.0f, 0.0f, 1.0f, 0.0f)]
+ [Row(0.0f, 1.0f, 0.54030230586813977, 0.8414709848078965)]
+ [Row(-1.0f, 1.0f, 0.19876611034641295, 0.30955987565311222)]
+ [Row(-111.1, 111.1, -2.3259065941590448e-49, -5.1181940185795617e-49)]
+ public void CanComputeExponential(float real, float imag, float expectedReal, float expectedImag)
+ {
+ var value = new Complex32(real, imag);
+ var expected = new Complex32(expectedReal, expectedImag);
+ AssertHelpers.AlmostEqual(expected, value.Exponential(), 7);
+ }
+
+
+ [Test]
+ [Row(0.0f, 0.0f, float.NegativeInfinity, 0.0f)]
+ [Row(0.0f, 1.0f, 0.0f, 1.5707963267948966)]
+ [Row(-1.0f, 1.0f, 0.34657359027997264, 2.3561944901923448)]
+ [Row(-111.1, 111.1, 5.0570042869255571, 2.3561944901923448)]
+ [Row(111.1, -111.1, 5.0570042869255571, -0.78539816339744828)]
+ public void CanComputeNaturalLogarithm(float real, float imag, float expectedReal, float expectedImag)
+ {
+ var value = new Complex32(real, imag);
+ var expected = new Complex32(expectedReal, expectedImag);
+ AssertHelpers.AlmostEqual(expected, value.NaturalLogarithm(), 7);
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanComputePower()
+ {
+ var a = new Complex32(1.19209289550780998537e-7f, 1.19209289550780998537e-7f);
+ var b = new Complex32(1.19209289550780998537e-7f, 1.19209289550780998537e-7f);
+ AssertHelpers.AlmostEqual(
+ new Complex32(9.99998047207974718744e-1f, -1.76553541154378695012e-6f), a.Power(b), 7);
+ a = new Complex32(0.0f, 1.19209289550780998537e-7f);
+ b = new Complex32(0.0f, -1.19209289550780998537e-7f);
+ AssertHelpers.AlmostEqual(new Complex32(1.00000018725172576491f, 1.90048076369011843105e-6f), a.Power(b), 7);
+ a = new Complex32(0.0f, -1.19209289550780998537e-7f);
+ b = new Complex32(0.0f, 0.5f);
+ AssertHelpers.AlmostEqual(new Complex32(-2.56488189382693049636e-1f, -2.17823120666116144959f), a.Power(b), 6);
+ a = new Complex32(0.0f, 0.5f);
+ b = new Complex32(0.0f, -0.5f);
+ AssertHelpers.AlmostEqual(new Complex32(2.06287223508090495171f, 7.45007062179724087859e-1f), a.Power(b), 7);
+ a = new Complex32(0.0f, -0.5f);
+ b = new Complex32(0.0f, 1.0f);
+ AssertHelpers.AlmostEqual(new Complex32(3.70040633557002510874f, -3.07370876701949232239f), a.Power(b), 7);
+ a = new Complex32(0.0f, 2.0f);
+ b = new Complex32(0.0f, -2.0f);
+ AssertHelpers.AlmostEqual(new Complex32(4.24532146387429353891f, -2.27479427903521192648e1f), a.Power(b), 7);
+ a = new Complex32(0.0f, -8.388608e6f);
+ b = new Complex32(1.19209289550780998537e-7f, 0.0f);
+ AssertHelpers.AlmostEqual(new Complex32(1.00000190048219620166f, -1.87253870018168043834e-7f), a.Power(b), 7);
+ a = new Complex32(0.0f, 0.0f);
+ b = new Complex32(0.0f, 0.0f);
+ AssertHelpers.AlmostEqual(new Complex32(1.0f, 0.0f), a.Power(b), 7);
+ a = new Complex32(0.0f, 0.0f);
+ b = new Complex32(1.0f, 0.0f);
+ AssertHelpers.AlmostEqual(new Complex32(0.0f, 0.0f), a.Power(b), 7);
+ a = new Complex32(0.0f, 0.0f);
+ b = new Complex32(-1.0f, 0.0f);
+ AssertHelpers.AlmostEqual(new Complex32(float.PositiveInfinity, 0.0f), a.Power(b), 7);
+ a = new Complex32(0.0f, 0.0f);
+ b = new Complex32(-1.0f, 1.0f);
+ 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);
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanComputeRoot()
+ {
+ var a = new Complex32(1.19209289550780998537e-7f, 1.19209289550780998537e-7f);
+ var b = new Complex32(1.19209289550780998537e-7f, 1.19209289550780998537e-7f);
+ AssertHelpers.AlmostEqual(new Complex32(0.0f, 0.0f), a.Root(b), 7);
+ a = new Complex32(0.0f, -1.19209289550780998537e-7f);
+ b = new Complex32(0.0f, 0.5f);
+ AssertHelpers.AlmostEqual(new Complex32(0.038550761943650161f, 0.019526430428319544f), a.Root(b), 6);
+ a = new Complex32(0.0f, 0.5f);
+ b = new Complex32(0.0f, -0.5f);
+ AssertHelpers.AlmostEqual(new Complex32(0.007927894711475968f, -0.042480480425152213f), a.Root(b), 6);
+ a = new Complex32(0.0f, -0.5f);
+ b = new Complex32(0.0f, 1.0f);
+ AssertHelpers.AlmostEqual(new Complex32(0.15990905692806806f, 0.13282699942462053f), a.Root(b), 7);
+ a = new Complex32(0.0f, 2.0f);
+ b = new Complex32(0.0f, -2.0f);
+ AssertHelpers.AlmostEqual(new Complex32(0.42882900629436788f, 0.15487175246424678f), a.Root(b), 7);
+ a = new Complex32(0.0f, -8.388608e6f);
+ b = new Complex32(1.19209289550780998537e-7f, 0.0f);
+ AssertHelpers.AlmostEqual(new Complex32(float.PositiveInfinity, float.NegativeInfinity), a.Root(b), 7);
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanComputeSquare()
+ {
+ var complex = new Complex32(1.19209289550780998537e-7f, 1.19209289550780998537e-7f);
+ AssertHelpers.AlmostEqual(new Complex32(0, 2.8421709430403888e-14f), complex.Square(), 7);
+ complex = new Complex32(0.0f, 1.19209289550780998537e-7f);
+ AssertHelpers.AlmostEqual(new Complex32(-1.4210854715201944e-14f, 0.0f), complex.Square(), 7);
+ complex = new Complex32(0.0f, -1.19209289550780998537e-7f);
+ AssertHelpers.AlmostEqual(new Complex32(-1.4210854715201944e-14f, 0.0f), complex.Square(), 7);
+ complex = new Complex32(0.0f, 0.5f);
+ AssertHelpers.AlmostEqual(new Complex32(-0.25f, 0.0f), complex.Square(), 7);
+ complex = new Complex32(0.0f, -0.5f);
+ AssertHelpers.AlmostEqual(new Complex32(-0.25f, 0.0f), complex.Square(), 7);
+ complex = new Complex32(0.0f, -8.388608e6f);
+ AssertHelpers.AlmostEqual(new Complex32(-70368744177664.0f, 0.0f), complex.Square(), 7);
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanComputeSquareRoot()
+ {
+ var complex = new Complex32(1.19209289550780998537e-7f, 1.19209289550780998537e-7f);
+ AssertHelpers.AlmostEqual(
+ new Complex32(0.00037933934912842666f, 0.00015712750315077684f), complex.SquareRoot(), 7);
+ complex = new Complex32(0.0f, 1.19209289550780998537e-7f);
+ AssertHelpers.AlmostEqual(
+ new Complex32(0.00024414062499999973f, 0.00024414062499999976f), complex.SquareRoot(), 7);
+ complex = new Complex32(0.0f, -1.19209289550780998537e-7f);
+ AssertHelpers.AlmostEqual(
+ new Complex32(0.00024414062499999973f, -0.00024414062499999976f), complex.SquareRoot(), 7);
+ complex = new Complex32(0.0f, 0.5f);
+ AssertHelpers.AlmostEqual(new Complex32(0.5f, 0.5f), complex.SquareRoot(), 7);
+ complex = new Complex32(0.0f, -0.5f);
+ AssertHelpers.AlmostEqual(new Complex32(0.5f, -0.5f), complex.SquareRoot(), 7);
+ complex = new Complex32(0.0f, -8.388608e6f);
+ AssertHelpers.AlmostEqual(new Complex32(2048.0f, -2048.0f), complex.SquareRoot(), 7);
+ complex = new Complex32(8.388608e6f, 1.19209289550780998537e-7f);
+ AssertHelpers.AlmostEqual(new Complex32(2896.3093757400989f, 2.0579515874459933e-11f), complex.SquareRoot(), 7);
+ complex = new Complex32(0.0f, 0.0f);
+ AssertHelpers.AlmostEqual(Complex32.Zero, complex.SquareRoot(), 7);
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanConvertDoubleToComplex()
+ {
+ AssertEx.That(() => ((Complex32)float.NaN).IsNaN);
+ AssertEx.That(() => ((Complex32)float.NegativeInfinity).IsInfinity);
+ Assert.AreEqual(1.1f, new Complex32(1.1f, 0));
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanCreateComplexNumberUsingTheConstructor()
+ {
+ var complex = new Complex32(1.1f, -2.2f);
+ Assert.AreEqual(1.1f, complex.Real, "Real part is 1.1f.");
+ Assert.AreEqual(-2.2f, complex.Imaginary, "Imaginary part is -2.2f.");
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanCreateComplexNumberWithModulusArgument()
+ {
+ var complex = Complex32.WithModulusArgument(2, (float)-Math.PI / 6);
+ Assert.AreApproximatelyEqual((float)Math.Sqrt(3), complex.Real, 1e-7f, "Real part is Sqrt(3).");
+ Assert.AreApproximatelyEqual(-1.0f, complex.Imaginary, 1e-7f, "Imaginary part is -1.");
+ }
+
+
+ [Test]
+ [MultipleAsserts]
+ public void CanCreateComplexNumberWithRealImaginaryIntializer()
+ {
+ var complex = Complex32.WithRealImaginary(1.1f, -2.2f);
+ Assert.AreEqual(1.1f, complex.Real, "Real part is 1.1f.");
+ Assert.AreEqual(-2.2f, complex.Imaginary, "Imaginary part is -2.2f.");
+ }
+
+ [Test]
+ public void CanDetermineIfImaginaryUnit()
+ {
+ var complex = new Complex32(0, 1);
+ Assert.IsTrue(complex.IsImaginaryOne, "Imaginary unit");
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanDetermineIfInfinity()
+ {
+ var complex = new Complex32(float.PositiveInfinity, 1);
+ Assert.IsTrue(complex.IsInfinity, "Real part is infinity.");
+ complex = new Complex32(1, float.NegativeInfinity);
+ Assert.IsTrue(complex.IsInfinity, "Imaginary part is infinity.");
+ complex = new Complex32(float.NegativeInfinity, float.PositiveInfinity);
+ Assert.IsTrue(complex.IsInfinity, "Both parts are infinity.");
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanDetermineIfNaN()
+ {
+ var complex = new Complex32(float.NaN, 1);
+ Assert.IsTrue(complex.IsNaN, "Real part is NaN.");
+ complex = new Complex32(1, float.NaN);
+ Assert.IsTrue(complex.IsNaN, "Imaginary part is NaN.");
+ complex = new Complex32(float.NaN, float.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.");
+ }
+
+ [Test]
+ public void CanDetermineIfRealNonNegativeNumber()
+ {
+ var complex = new Complex32(1, 0);
+ 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.");
+ }
+
+ [Test]
+ public void CanDetermineIfZeroValueComplexNumber()
+ {
+ var complex = new Complex32(0, 0);
+ Assert.IsTrue(complex.IsZero, "Zero complex number.");
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanDivideComplexNumberAndDoubleUsingOperators()
+ {
+ 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);
+ Assert.AreEqual(Complex32.Infinity, Complex32.One / 0);
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanDivideTwoComplexNumbers()
+ {
+ 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));
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanDivideTwoComplexNumbersUsingOperators()
+ {
+ 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);
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanMultipleComplexNumberAndDoubleUsingOperators()
+ {
+ 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));
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanMultipleTwoComplexNumbers()
+ {
+ AssertEx.That(() => Complex32.NaN.Multiply(Complex32.One).IsNaN);
+ Assert.AreEqual(new Complex32(0, 16), new Complex32(4, -4).Multiply(new Complex32(-2, 2)));
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanMultipleTwoComplexNumbersUsingOperators()
+ {
+ AssertEx.That(() => (Complex32.NaN * Complex32.One).IsNaN);
+ Assert.AreEqual(new Complex32(0, 16), new Complex32(4, -4) * new Complex32(-2, 2));
+ }
+
+ [Test]
+ public void CanNegateValue()
+ {
+ var complex = new Complex32(1.1f, -2.2f);
+ Assert.AreEqual(new Complex32(-1.1f, 2.2f), complex.Negate());
+ }
+
+ [Test]
+ public void CanNegateValueUsingOperator()
+ {
+ var complex = new Complex32(1.1f, -2.2f);
+ Assert.AreEqual(new Complex32(-1.1f, 2.2f), -complex);
+ }
+
+ [Test]
+ [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.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)));
+ AssertEx.That(() => -2.2f - new Complex32(-1.1f, 2.2f) == new Complex32(-1.1f, -2.2f));
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanSubtractTwoComplexNumbers()
+ {
+ 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);
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanTestForEquality()
+ {
+ Assert.AreNotEqual(Complex32.NaN, Complex32.NaN);
+ Assert.AreEqual(Complex32.Infinity, Complex32.Infinity);
+ Assert.AreEqual(new Complex32(1.1f, -2.2f), new Complex32(1.1f, -2.2f));
+ Assert.AreNotEqual(new Complex32(-1.1f, 2.2f), new Complex32(1.1f, -2.2f));
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanTestForEqualityUsingOperators()
+ {
+ AssertEx.That(() => Complex32.NaN != Complex32.NaN);
+ AssertEx.That(() => Complex32.Infinity == Complex32.Infinity);
+ AssertEx.That(() => new Complex32(1.1f, -2.2f) == new Complex32(1.1f, -2.2f));
+ AssertEx.That(() => new Complex32(-1.1f, 2.2f) != new Complex32(1.1f, -2.2f));
+ }
+
+ [Test]
+ public void CanUsePlus()
+ {
+ var complex = new Complex32(1.1f, -2.2f);
+ Assert.AreEqual(complex, complex.Plus());
+ }
+
+ [Test]
+ public void CanUsePlusOperator()
+ {
+ var complex = new Complex32(1.1f, -2.2f);
+ Assert.AreEqual(complex, +complex);
+ }
+
+ [Test]
+ public void WithModulusArgumentThrowsArgumentOutOfRangeException()
+ {
+ Assert.Throws(
+ () => Complex32.WithModulusArgument(-1, 1), "Throws exception because modulus is negative.");
+ }
+
+ [Test]
+ [Row(0.0f, 0.0f, 0.0f)]
+ [Row(0.0f, 1.0f, 1.0f)]
+ [Row(-1.0f, 1.0f, 1.4142135623730951)]
+ [Row(-111.1, 111.1, 157.11912677965086)]
+ public void CanComputeMagnitude(float real, float imag, float expected)
+ {
+ Assert.AreEqual(expected, new Complex32(real, imag).Magnitude);
+ }
+
+
+ [Test]
+ [Row(float.PositiveInfinity, float.PositiveInfinity, Constants.Sqrt1Over2, Constants.Sqrt1Over2)]
+ [Row(float.PositiveInfinity, float.NegativeInfinity, Constants.Sqrt1Over2, -Constants.Sqrt1Over2)]
+ [Row(float.NegativeInfinity, float.PositiveInfinity, -Constants.Sqrt1Over2, -Constants.Sqrt1Over2)]
+ [Row(float.NegativeInfinity, float.NegativeInfinity, -Constants.Sqrt1Over2, Constants.Sqrt1Over2)]
+ [Row(0.0f, 0.0f, 0.0f, 0.0f)]
+ [Row(-1.0f, 1.0f, -0.70710678118654746, 0.70710678118654746)]
+ [Row(-111.1, 111.1, -0.70710678118654746, 0.70710678118654746)]
+ public void CanComputeSign(float real, float imag, float expectedReal, float expectedImag)
+ {
+ Assert.AreEqual(new Complex32(expectedReal, expectedImag), new Complex32(real, imag).Sign);
+ }
+
+ [Test]
+ public void CanConvertDecimalToComplex()
+ {
+ var orginal = new decimal(1.234567890);
+ var complex = (Complex32)orginal;
+ Assert.AreEqual((float)1.234567890, complex.Real);
+ Assert.AreEqual(0.0f, complex.Imaginary);
+ }
+
+ [Test]
+ public void CanConvertByteToComplex()
+ {
+ const byte orginal = 123;
+ var complex = (Complex32)orginal;
+ Assert.AreEqual(123, complex.Real);
+ Assert.AreEqual(0.0f, complex.Imaginary);
+ }
+
+ [Test]
+ public void CanConvertShortToComplex()
+ {
+ const short orginal = 123;
+ var complex = (Complex32)orginal;
+ Assert.AreEqual(123, complex.Real);
+ Assert.AreEqual(0.0f, complex.Imaginary);
+ }
+
+ [Test]
+ public void CanConvertIntToComplex()
+ {
+ const int orginal = 123;
+ var complex = (Complex32)orginal;
+ Assert.AreEqual(123, complex.Real);
+ Assert.AreEqual(0.0f, complex.Imaginary);
+ }
+
+ [Test]
+ public void CanConvertLongToComplex()
+ {
+ const long orginal = 123;
+ var complex = (Complex32)orginal;
+ Assert.AreEqual(123, complex.Real);
+ Assert.AreEqual(0.0f, complex.Imaginary);
+ }
+
+ [Test]
+ public void CanConvertUIntToComplex()
+ {
+ const uint orginal = 123;
+ var complex = (Complex32)orginal;
+ Assert.AreEqual(123, complex.Real);
+ Assert.AreEqual(0.0f, complex.Imaginary);
+ }
+
+ [Test]
+ public void CanConvertULongToComplex()
+ {
+ const ulong orginal = 123;
+ var complex = (Complex32)orginal;
+ Assert.AreEqual(123, complex.Real);
+ Assert.AreEqual(0.0f, complex.Imaginary);
+ }
+
+ [Test]
+ public void CanConvertFloatToComplex()
+ {
+ const float orginal = 123.456789f;
+ var complex = (Complex32)orginal;
+ Assert.AreEqual(123.456789f, complex.Real);
+ Assert.AreEqual(0.0f, complex.Imaginary);
+ }
+
+ [Test]
+ public void CanConvertComplexToComplex32()
+ {
+ var complex32 = new Complex(123.456, -78.9);
+ var complex = (Complex32)complex32;
+ Assert.AreEqual(123.456f, complex.Real);
+ Assert.AreEqual(-78.9f, complex.Imaginary);
+ }
+
+ [Test]
+ public void CanGetConjugate()
+ {
+ var complex = new Complex(123.456, -78.9);
+ var conjugate = complex.Conjugate;
+ Assert.AreEqual(complex.Real, conjugate.Real);
+ Assert.AreEqual(-complex.Imaginary, conjugate.Imaginary);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/UnitTests/ComplexTests/ComplexTest.cs b/src/UnitTests/ComplexTests/ComplexTest.cs
index 3e52783d..454df4f7 100644
--- a/src/UnitTests/ComplexTests/ComplexTest.cs
+++ b/src/UnitTests/ComplexTests/ComplexTest.cs
@@ -794,12 +794,12 @@ namespace MathNet.Numerics.UnitTests.ComplexTests
}
[Test]
- public void CanConvertDoulbeComplex()
+ public void CanConvertComplex32ToComplex()
{
- const double orginal = 123.456789;
- var complex = (Complex)orginal;
- Assert.AreEqual(123.456789, complex.Real);
- Assert.AreEqual(0.0, complex.Imaginary);
+ 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);
}
}
}
\ No newline at end of file
diff --git a/src/UnitTests/PrecisionTest.cs b/src/UnitTests/PrecisionTest.cs
index 3dc5cac2..02e00e08 100644
--- a/src/UnitTests/PrecisionTest.cs
+++ b/src/UnitTests/PrecisionTest.cs
@@ -35,7 +35,7 @@ namespace MathNet.Numerics.UnitTests
public sealed class PrecisionTest
{
private const double _acceptableError = 1e-12;
- private readonly double _doublePrecision = System.Math.Pow(2, -53);
+ private readonly double _doublePrecision = Math.Pow(2, -53);
[Test]
public void Magnitude()
diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj
index d669620c..fbb4fbf2 100644
--- a/src/UnitTests/UnitTests.csproj
+++ b/src/UnitTests/UnitTests.csproj
@@ -64,6 +64,8 @@
+
+