You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
401 lines
12 KiB
401 lines
12 KiB
5 years ago
|
#if NET20 || NET30 || NET35 || !NET_4_6
|
||
|
|
||
|
// Complex.cs: Complex number support
|
||
|
|
||
|
// Author:
|
||
|
// Miguel de Icaza (miguel@gnome.org)
|
||
|
// Marek Safar (marek.safar@gmail.com)
|
||
|
// Jb Evain (jbevain@novell.com)
|
||
|
|
||
|
// Copyright 2009, 2010 Novell, Inc.
|
||
|
|
||
|
// 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 System.Numerics
|
||
|
{
|
||
|
public struct Complex : IEquatable<Complex>, IFormattable
|
||
|
{
|
||
|
public static readonly Complex ImaginaryOne = new Complex(0, 1);
|
||
|
public static readonly Complex One = new Complex(1, 0);
|
||
|
public static readonly Complex Zero = new Complex(0, 0);
|
||
|
private readonly double _imaginary;
|
||
|
private readonly double _real;
|
||
|
|
||
|
public Complex(double real, double imaginary)
|
||
|
{
|
||
|
_imaginary = imaginary;
|
||
|
_real = real;
|
||
|
}
|
||
|
|
||
|
public double Imaginary
|
||
|
{
|
||
|
get { return _imaginary; }
|
||
|
}
|
||
|
|
||
|
public double Magnitude
|
||
|
{
|
||
|
get { return Math.Sqrt((_imaginary * _imaginary) + (_real * _real)); }
|
||
|
}
|
||
|
|
||
|
public double Phase
|
||
|
{
|
||
|
get { return Math.Atan2(_imaginary, _real); }
|
||
|
}
|
||
|
|
||
|
public double Real
|
||
|
{
|
||
|
get { return _real; }
|
||
|
}
|
||
|
|
||
|
private double MagnitudeSquared
|
||
|
{
|
||
|
get { return (_imaginary * _imaginary) + (_real * _real); }
|
||
|
}
|
||
|
|
||
|
public static double Abs(Complex value)
|
||
|
{
|
||
|
return Math.Sqrt((value._imaginary * value._imaginary) + (value._real * value._real));
|
||
|
}
|
||
|
|
||
|
public static Complex Acos(Complex value)
|
||
|
{
|
||
|
return -ImaginaryOne * Log(value + (ImaginaryOne * Sqrt(One - (value * value))));
|
||
|
}
|
||
|
|
||
|
public static Complex Add(Complex left, Complex right)
|
||
|
{
|
||
|
return new Complex
|
||
|
(
|
||
|
left._real + right._real,
|
||
|
left._imaginary + right._imaginary
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static Complex Asin(Complex value)
|
||
|
{
|
||
|
return -ImaginaryOne * Log((ImaginaryOne * value) + Sqrt(One - (value * value)));
|
||
|
}
|
||
|
|
||
|
public static Complex Atan(Complex value)
|
||
|
{
|
||
|
return (ImaginaryOne / new Complex(2, 0)) * (Log(One - (ImaginaryOne * value)) - Log(One + (ImaginaryOne * value)));
|
||
|
}
|
||
|
|
||
|
public static Complex Conjugate(Complex value)
|
||
|
{
|
||
|
return new Complex(value._real, -value._imaginary);
|
||
|
}
|
||
|
|
||
|
public static Complex Cos(Complex value)
|
||
|
{
|
||
|
return new Complex
|
||
|
(
|
||
|
Math.Cos(value._real) * Math.Cosh(value._imaginary),
|
||
|
-Math.Sin(value._real) * Math.Sinh(value._imaginary)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static Complex Cosh(Complex value)
|
||
|
{
|
||
|
return new Complex
|
||
|
(
|
||
|
Math.Cosh(value._real) * Math.Cos(value._imaginary),
|
||
|
-Math.Sinh(value._real) * Math.Sin(value._imaginary)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static Complex Divide(Complex dividend, Complex divisor)
|
||
|
{
|
||
|
var divisorMagnitudeSquared = divisor.MagnitudeSquared;
|
||
|
return new Complex
|
||
|
(
|
||
|
((dividend._real * divisor._real) + (dividend._imaginary * divisor._imaginary)) / divisorMagnitudeSquared,
|
||
|
((dividend._imaginary * divisor._real) - (dividend._real * divisor._imaginary)) / divisorMagnitudeSquared
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static Complex Exp(Complex value)
|
||
|
{
|
||
|
var expReal = Math.Exp(value._real);
|
||
|
return new Complex
|
||
|
(
|
||
|
expReal * Math.Cos(value._imaginary),
|
||
|
expReal * Math.Sin(value._imaginary)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static explicit operator Complex(decimal value)
|
||
|
{
|
||
|
return new Complex((double)value, 0);
|
||
|
}
|
||
|
|
||
|
public static explicit operator Complex(BigInteger value)
|
||
|
{
|
||
|
return new Complex((double)value, 0);
|
||
|
}
|
||
|
|
||
|
public static Complex FromPolarCoordinates(double magnitude, double phase)
|
||
|
{
|
||
|
return new Complex
|
||
|
(
|
||
|
magnitude * Math.Cos(phase),
|
||
|
magnitude * Math.Sin(phase)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static implicit operator Complex(byte value)
|
||
|
{
|
||
|
return new Complex(value, 0);
|
||
|
}
|
||
|
|
||
|
public static implicit operator Complex(double value)
|
||
|
{
|
||
|
return new Complex(value, 0);
|
||
|
}
|
||
|
|
||
|
public static implicit operator Complex(short value)
|
||
|
{
|
||
|
return new Complex(value, 0);
|
||
|
}
|
||
|
|
||
|
public static implicit operator Complex(int value)
|
||
|
{
|
||
|
return new Complex(value, 0);
|
||
|
}
|
||
|
|
||
|
public static implicit operator Complex(long value)
|
||
|
{
|
||
|
return new Complex(value, 0);
|
||
|
}
|
||
|
|
||
|
//[CLSCompliant(false)]
|
||
|
public static implicit operator Complex(sbyte value)
|
||
|
{
|
||
|
return new Complex(value, 0);
|
||
|
}
|
||
|
|
||
|
public static implicit operator Complex(float value)
|
||
|
{
|
||
|
return new Complex(value, 0);
|
||
|
}
|
||
|
|
||
|
//[CLSCompliant(false)]
|
||
|
public static implicit operator Complex(ushort value)
|
||
|
{
|
||
|
return new Complex(value, 0);
|
||
|
}
|
||
|
|
||
|
//[CLSCompliant(false)]
|
||
|
public static implicit operator Complex(uint value)
|
||
|
{
|
||
|
return new Complex(value, 0);
|
||
|
}
|
||
|
|
||
|
//[CLSCompliant(false)]
|
||
|
public static implicit operator Complex(ulong value)
|
||
|
{
|
||
|
return new Complex(value, 0);
|
||
|
}
|
||
|
|
||
|
public static Complex Log(Complex value)
|
||
|
{
|
||
|
return new Complex
|
||
|
(
|
||
|
Math.Log(Abs(value)),
|
||
|
value.Phase
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static Complex Log(Complex value, double baseValue)
|
||
|
{
|
||
|
return Log(value) / Log(new Complex(baseValue, 0));
|
||
|
}
|
||
|
|
||
|
public static Complex Log10(Complex value)
|
||
|
{
|
||
|
return Log(value, 10);
|
||
|
}
|
||
|
|
||
|
public static Complex Multiply(Complex left, Complex right)
|
||
|
{
|
||
|
return new Complex
|
||
|
(
|
||
|
(left._real * right._real) - (left._imaginary * right._imaginary),
|
||
|
(left._real * right._imaginary) + (left._imaginary * right._real)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static Complex Negate(Complex value)
|
||
|
{
|
||
|
return -value;
|
||
|
}
|
||
|
|
||
|
public static Complex operator -(Complex left, Complex right)
|
||
|
{
|
||
|
return new Complex
|
||
|
(
|
||
|
left._real - right._real,
|
||
|
left._imaginary - right._imaginary
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static Complex operator -(Complex value)
|
||
|
{
|
||
|
return new Complex(-value._real, -value._imaginary);
|
||
|
}
|
||
|
|
||
|
public static bool operator !=(Complex left, Complex right)
|
||
|
{
|
||
|
return !left._real.Equals(right._real) || !left._imaginary.Equals(right._imaginary);
|
||
|
}
|
||
|
|
||
|
public static Complex operator *(Complex left, Complex right)
|
||
|
{
|
||
|
return new Complex
|
||
|
(
|
||
|
(left._real * right._real) - (left._imaginary * right._imaginary),
|
||
|
(left._real * right._imaginary) + (left._imaginary * right._real)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static Complex operator /(Complex left, Complex right)
|
||
|
{
|
||
|
var rsri = (right._real * right._real) + (right._imaginary * right._imaginary);
|
||
|
return new Complex
|
||
|
(
|
||
|
((left._real * right._real) + (left._imaginary * right._imaginary)) / rsri,
|
||
|
((left._imaginary * right._real) - (left._real * right._imaginary)) / rsri
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static Complex operator +(Complex left, Complex right)
|
||
|
{
|
||
|
return new Complex
|
||
|
(
|
||
|
left._real + right._real,
|
||
|
left._imaginary + right._imaginary
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static bool operator ==(Complex left, Complex right)
|
||
|
{
|
||
|
return left._real.Equals(right._real) && left._imaginary.Equals(right._imaginary);
|
||
|
}
|
||
|
|
||
|
public static Complex Pow(Complex value, double power)
|
||
|
{
|
||
|
return Pow(value, new Complex(power, 0));
|
||
|
}
|
||
|
|
||
|
public static Complex Pow(Complex value, Complex power)
|
||
|
{
|
||
|
return Exp(Log(value) * power);
|
||
|
}
|
||
|
|
||
|
public static Complex Reciprocal(Complex value)
|
||
|
{
|
||
|
return value == Zero ? value : One / value;
|
||
|
}
|
||
|
|
||
|
public static Complex Sin(Complex value)
|
||
|
{
|
||
|
return new Complex
|
||
|
(
|
||
|
Math.Sin(value._real) * Math.Cosh(value._imaginary),
|
||
|
Math.Cos(value._real) * Math.Sinh(value._imaginary)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static Complex Sinh(Complex value)
|
||
|
{
|
||
|
return new Complex
|
||
|
(
|
||
|
Math.Sinh(value._real) * Math.Cos(value._imaginary),
|
||
|
Math.Cosh(value._real) * Math.Sin(value._imaginary)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static Complex Sqrt(Complex value)
|
||
|
{
|
||
|
return FromPolarCoordinates(Math.Sqrt(value.Magnitude), value.Phase / 2);
|
||
|
}
|
||
|
|
||
|
public static Complex Subtract(Complex left, Complex right)
|
||
|
{
|
||
|
return new Complex
|
||
|
(
|
||
|
left._real - right._real,
|
||
|
left._imaginary - right._imaginary
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static Complex Tan(Complex value)
|
||
|
{
|
||
|
return Sin(value) / Cos(value);
|
||
|
}
|
||
|
|
||
|
public static Complex Tanh(Complex value)
|
||
|
{
|
||
|
return Sinh(value) / Cosh(value);
|
||
|
}
|
||
|
|
||
|
public bool Equals(Complex value)
|
||
|
{
|
||
|
return _real.Equals(value._real) && _imaginary.Equals(value._imaginary);
|
||
|
}
|
||
|
|
||
|
public override bool Equals(object obj)
|
||
|
{
|
||
|
if (obj is Complex)
|
||
|
{
|
||
|
var other = (Complex)obj;
|
||
|
return _real.Equals(other._real) && _imaginary.Equals(other._imaginary);
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public override int GetHashCode()
|
||
|
{
|
||
|
return _real.GetHashCode() ^ _imaginary.GetHashCode();
|
||
|
}
|
||
|
|
||
|
public override string ToString()
|
||
|
{
|
||
|
return string.Format("({0}, {1})", _real, _imaginary);
|
||
|
}
|
||
|
|
||
|
public string ToString(IFormatProvider provider)
|
||
|
{
|
||
|
return string.Format(provider, "({0}, {1})", _real, _imaginary);
|
||
|
}
|
||
|
|
||
|
public string ToString(string format)
|
||
|
{
|
||
|
return string.Format("({0}, {1})", _real.ToString(format), _imaginary.ToString(format));
|
||
|
}
|
||
|
|
||
|
public string ToString(string format, IFormatProvider provider)
|
||
|
{
|
||
|
return string.Format("({0}, {1})", _real.ToString(format, provider), _imaginary.ToString(format, provider));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|