Files
SuperVPN/output/Libraries/AForge.Math/AForge/Math/Complex.cs
2025-10-09 09:57:24 +09:00

474 lines
9.2 KiB
C#

using System;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
namespace AForge.Math;
public struct Complex : ICloneable, ISerializable
{
public double Re;
public double Im;
public static readonly Complex Zero = new Complex(0.0, 0.0);
public static readonly Complex One = new Complex(1.0, 0.0);
public static readonly Complex I = new Complex(0.0, 1.0);
public double Magnitude => System.Math.Sqrt(Re * Re + Im * Im);
public double Phase => System.Math.Atan2(Im, Re);
public double SquaredMagnitude => Re * Re + Im * Im;
public Complex(double re, double im)
{
Re = re;
Im = im;
}
public Complex(Complex c)
{
Re = c.Re;
Im = c.Im;
}
public static Complex Add(Complex a, Complex b)
{
return new Complex(a.Re + b.Re, a.Im + b.Im);
}
public static Complex Add(Complex a, double s)
{
return new Complex(a.Re + s, a.Im);
}
public static void Add(Complex a, Complex b, ref Complex result)
{
result.Re = a.Re + b.Re;
result.Im = a.Im + b.Im;
}
public static void Add(Complex a, double s, ref Complex result)
{
result.Re = a.Re + s;
result.Im = a.Im;
}
public static Complex Subtract(Complex a, Complex b)
{
return new Complex(a.Re - b.Re, a.Im - b.Im);
}
public static Complex Subtract(Complex a, double s)
{
return new Complex(a.Re - s, a.Im);
}
public static Complex Subtract(double s, Complex a)
{
return new Complex(s - a.Re, a.Im);
}
public static void Subtract(Complex a, Complex b, ref Complex result)
{
result.Re = a.Re - b.Re;
result.Im = a.Im - b.Im;
}
public static void Subtract(Complex a, double s, ref Complex result)
{
result.Re = a.Re - s;
result.Im = a.Im;
}
public static void Subtract(double s, Complex a, ref Complex result)
{
result.Re = s - a.Re;
result.Im = a.Im;
}
public static Complex Multiply(Complex a, Complex b)
{
double re = a.Re;
double im = a.Im;
double re2 = b.Re;
double im2 = b.Im;
return new Complex(re * re2 - im * im2, re * im2 + im * re2);
}
public static Complex Multiply(Complex a, double s)
{
return new Complex(a.Re * s, a.Im * s);
}
public static void Multiply(Complex a, Complex b, ref Complex result)
{
double re = a.Re;
double im = a.Im;
double re2 = b.Re;
double im2 = b.Im;
result.Re = re * re2 - im * im2;
result.Im = re * im2 + im * re2;
}
public static void Multiply(Complex a, double s, ref Complex result)
{
result.Re = a.Re * s;
result.Im = a.Im * s;
}
public static Complex Divide(Complex a, Complex b)
{
double re = a.Re;
double im = a.Im;
double re2 = b.Re;
double im2 = b.Im;
double num = re2 * re2 + im2 * im2;
if (num == 0.0)
{
throw new DivideByZeroException("Can not divide by zero.");
}
double num2 = 1.0 / num;
return new Complex((re * re2 + im * im2) * num2, (im * re2 - re * im2) * num2);
}
public static Complex Divide(Complex a, double s)
{
if (s == 0.0)
{
throw new DivideByZeroException("Can not divide by zero.");
}
return new Complex(a.Re / s, a.Im / s);
}
public static Complex Divide(double s, Complex a)
{
if (a.Re == 0.0 || a.Im == 0.0)
{
throw new DivideByZeroException("Can not divide by zero.");
}
return new Complex(s / a.Re, s / a.Im);
}
public static void Divide(Complex a, Complex b, ref Complex result)
{
double re = a.Re;
double im = a.Im;
double re2 = b.Re;
double im2 = b.Im;
double num = re2 * re2 + im2 * im2;
if (num == 0.0)
{
throw new DivideByZeroException("Can not divide by zero.");
}
double num2 = 1.0 / num;
result.Re = (re * re2 + im * im2) * num2;
result.Im = (im * re2 - re * im2) * num2;
}
public static void Divide(Complex a, double s, ref Complex result)
{
if (s == 0.0)
{
throw new DivideByZeroException("Can not divide by zero.");
}
result.Re = a.Re / s;
result.Im = a.Im / s;
}
public static void Divide(double s, Complex a, ref Complex result)
{
if (a.Re == 0.0 || a.Im == 0.0)
{
throw new DivideByZeroException("Can not divide by zero.");
}
result.Re = s / a.Re;
result.Im = s / a.Im;
}
public static Complex Negate(Complex a)
{
return new Complex(0.0 - a.Re, 0.0 - a.Im);
}
public static bool ApproxEqual(Complex a, Complex b)
{
return ApproxEqual(a, b, 8.881784197001252E-16);
}
public static bool ApproxEqual(Complex a, Complex b, double tolerance)
{
if (System.Math.Abs(a.Re - b.Re) <= tolerance)
{
return System.Math.Abs(a.Im - b.Im) <= tolerance;
}
return false;
}
public static Complex Parse(string s)
{
Regex regex = new Regex("\\((?<real>.*),(?<imaginary>.*)\\)", RegexOptions.None);
Match match = regex.Match(s);
if (match.Success)
{
return new Complex(double.Parse(match.Result("${real}")), double.Parse(match.Result("${imaginary}")));
}
throw new FormatException("String representation of the complex number is not correctly formatted.");
}
public static bool TryParse(string s, out Complex result)
{
try
{
Complex complex = Parse(s);
result = complex;
return true;
}
catch (FormatException)
{
result = default(Complex);
return false;
}
}
public static Complex Sqrt(Complex a)
{
Complex zero = Zero;
if (a.Re == 0.0 && a.Im == 0.0)
{
return zero;
}
if (a.Im == 0.0)
{
zero.Re = ((a.Re > 0.0) ? System.Math.Sqrt(a.Re) : System.Math.Sqrt(0.0 - a.Re));
zero.Im = 0.0;
}
else
{
double magnitude = a.Magnitude;
zero.Re = System.Math.Sqrt(0.5 * (magnitude + a.Re));
zero.Im = System.Math.Sqrt(0.5 * (magnitude - a.Re));
if (a.Im < 0.0)
{
zero.Im = 0.0 - zero.Im;
}
}
return zero;
}
public static Complex Log(Complex a)
{
Complex zero = Zero;
if (a.Re > 0.0 && a.Im == 0.0)
{
zero.Re = System.Math.Log(a.Re);
zero.Im = 0.0;
}
else if (a.Re == 0.0)
{
if (a.Im > 0.0)
{
zero.Re = System.Math.Log(a.Im);
zero.Im = System.Math.PI / 2.0;
}
else
{
zero.Re = System.Math.Log(0.0 - a.Im);
zero.Im = -System.Math.PI / 2.0;
}
}
else
{
zero.Re = System.Math.Log(a.Magnitude);
zero.Im = System.Math.Atan2(a.Im, a.Re);
}
return zero;
}
public static Complex Exp(Complex a)
{
Complex zero = Zero;
double num = System.Math.Exp(a.Re);
zero.Re = num * System.Math.Cos(a.Im);
zero.Im = num * System.Math.Sin(a.Im);
return zero;
}
public static Complex Sin(Complex a)
{
Complex zero = Zero;
if (a.Im == 0.0)
{
zero.Re = System.Math.Sin(a.Re);
zero.Im = 0.0;
}
else
{
zero.Re = System.Math.Sin(a.Re) * System.Math.Cosh(a.Im);
zero.Im = System.Math.Cos(a.Re) * System.Math.Sinh(a.Im);
}
return zero;
}
public static Complex Cos(Complex a)
{
Complex zero = Zero;
if (a.Im == 0.0)
{
zero.Re = System.Math.Cos(a.Re);
zero.Im = 0.0;
}
else
{
zero.Re = System.Math.Cos(a.Re) * System.Math.Cosh(a.Im);
zero.Im = (0.0 - System.Math.Sin(a.Re)) * System.Math.Sinh(a.Im);
}
return zero;
}
public static Complex Tan(Complex a)
{
Complex zero = Zero;
if (a.Im == 0.0)
{
zero.Re = System.Math.Tan(a.Re);
zero.Im = 0.0;
}
else
{
double num = 2.0 * a.Re;
double value = 2.0 * a.Im;
double num2 = System.Math.Cos(num) + System.Math.Cosh(num);
zero.Re = System.Math.Sin(num) / num2;
zero.Im = System.Math.Sinh(value) / num2;
}
return zero;
}
public override int GetHashCode()
{
return Re.GetHashCode() ^ Im.GetHashCode();
}
public override bool Equals(object obj)
{
if (!(obj is Complex))
{
return false;
}
return this == (Complex)obj;
}
public override string ToString()
{
return $"({Re}, {Im})";
}
public static bool operator ==(Complex u, Complex v)
{
if (u.Re == v.Re)
{
return u.Im == v.Im;
}
return false;
}
public static bool operator !=(Complex u, Complex v)
{
return !(u == v);
}
public static Complex operator -(Complex a)
{
return Negate(a);
}
public static Complex operator +(Complex a, Complex b)
{
return Add(a, b);
}
public static Complex operator +(Complex a, double s)
{
return Add(a, s);
}
public static Complex operator +(double s, Complex a)
{
return Add(a, s);
}
public static Complex operator -(Complex a, Complex b)
{
return Subtract(a, b);
}
public static Complex operator -(Complex a, double s)
{
return Subtract(a, s);
}
public static Complex operator -(double s, Complex a)
{
return Subtract(s, a);
}
public static Complex operator *(Complex a, Complex b)
{
return Multiply(a, b);
}
public static Complex operator *(double s, Complex a)
{
return Multiply(a, s);
}
public static Complex operator *(Complex a, double s)
{
return Multiply(a, s);
}
public static Complex operator /(Complex a, Complex b)
{
return Divide(a, b);
}
public static Complex operator /(Complex a, double s)
{
return Divide(a, s);
}
public static Complex operator /(double s, Complex a)
{
return Divide(s, a);
}
public static explicit operator Complex(float value)
{
return new Complex(value, 0.0);
}
public static explicit operator Complex(double value)
{
return new Complex(value, 0.0);
}
object ICloneable.Clone()
{
return new Complex(this);
}
public Complex Clone()
{
return new Complex(this);
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Real", Re);
info.AddValue("Imaginary", Im);
}
}