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
#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 |