using System; using System.Diagnostics; /* * This is a complex number class I wrote to use in unity (since Unity uses MonoDevelop) * If you like my work, and found use in it, * or want to encourage more useful classes in C#. * Please donate ^^ * Bitcoin Address: 1LdyAQHXdFVqzGzah45sGKhsQ8wDE6jyci * Good luck and enjoy. * */ namespace Assets.Scripts { public struct Complex { private double _realNumber; private double _imaginaryNumber; private static readonly Random _random = new Random(); public Double RealNumber { get { return _realNumber; } set { _realNumber = value; } } public Double ImaginaryNumber { get { return _imaginaryNumber; } set { _imaginaryNumber = value; } } public Complex(double real, double imaginary) { _realNumber = real; _imaginaryNumber = imaginary; } public Complex(Complex z) { _realNumber = z._realNumber; _imaginaryNumber = z._imaginaryNumber; } public void ComplexNumber(double real, double imaginary) { _realNumber = real; _imaginaryNumber = imaginary; } public static Complex Random() { var z = new Complex { RealNumber = _random.NextDouble(), ImaginaryNumber = _random.NextDouble() }; return z; } public static Complex Random(Double lowNumber) { return Random(lowNumber, 0); } public static Complex Random(Double lowNumber, Double highNumber) { var z = new Complex(); var range = highNumber - lowNumber; z.RealNumber = lowNumber + range*_random.NextDouble(); z.ImaginaryNumber = lowNumber + range*_random.NextDouble(); return z; } public static Complex operator +(Complex z1, Complex z2) { return new Complex(z1.RealNumber + z2.RealNumber, z1.ImaginaryNumber + z2.ImaginaryNumber); } public static Complex operator -(Complex z1, Complex z2) { return new Complex(z1.RealNumber - z2.RealNumber, z1.ImaginaryNumber - z2.ImaginaryNumber); } public static Complex operator -(Complex z) { z.RealNumber = -z.RealNumber; z.ImaginaryNumber = -z.ImaginaryNumber; return z; } public static Complex operator *(Complex z1, Complex z2) { return new Complex( z1.RealNumber * z2.RealNumber - z1.ImaginaryNumber *z2.ImaginaryNumber, z1.RealNumber * z2.ImaginaryNumber + z2.ImaginaryNumber * z2.RealNumber ); } static public Complex operator *(Complex z, double dval) { var z2 = new Complex { RealNumber = (z.RealNumber*dval), ImaginaryNumber = (z.ImaginaryNumber*dval) }; return z2; } static public Complex operator *( double dval, Complex z) { var z2 = new Complex { RealNumber = (z.RealNumber * dval), ImaginaryNumber = (z.ImaginaryNumber * dval) }; return z2; } public static Complex operator /(Complex z1, Complex z2) { var value = z2.RealNumber*z2.RealNumber + z2.ImaginaryNumber*z2.ImaginaryNumber; return new Complex( (z1.RealNumber * z2.RealNumber + z1.ImaginaryNumber * z2.ImaginaryNumber)/value, (z1.ImaginaryNumber * z2.RealNumber + z1.RealNumber * z2.ImaginaryNumber)/value ); } static public Complex operator /(Complex z, double dval) { var z2 = new Complex { RealNumber = z.RealNumber/dval, ImaginaryNumber = z.ImaginaryNumber/dval }; return z2; } public static bool operator ==(Complex z1, Complex z2) { return (z1.RealNumber == z2.RealNumber && z1.ImaginaryNumber == z2.ImaginaryNumber); } public static bool operator !=(Complex z1, Complex z2) { return !(z1 == z2); } public Complex Conjugate { get { return new Complex(_realNumber, -_imaginaryNumber); } } public double Norm { get { return Math.Sqrt(_realNumber * _realNumber + _imaginaryNumber * _imaginaryNumber); } } public double AbsoluteSquare { get { return (this * Conjugate).RealNumber; } } public double Modulus { get { return Math.Sqrt(_realNumber * _realNumber + _imaginaryNumber * _imaginaryNumber); } } public double Argument { get { return Math.Atan2(_imaginaryNumber, _realNumber); } } public static Complex Polar(double modulus, double argument) { return new Complex( modulus * Math.Cos(argument), modulus * Math.Sin(argument)); } public static Complex Exp(Complex z) { var value = Math.Exp(z.RealNumber); return new Complex( value * Math.Cos(z.ImaginaryNumber), value * Math.Sin(z.ImaginaryNumber)); } public static Complex Log(Complex z) { return new Complex(Math.Log(z.Modulus), z.Argument); } public static Complex Pow(Complex baseNumber, Complex index) { return Exp(index * Log(baseNumber)); } public static Complex Sqrt(Complex z) { var value = Math.Sqrt(z.RealNumber * z.RealNumber + z.ImaginaryNumber * z.ImaginaryNumber) + z.RealNumber; return new Complex( Math.Sqrt(0.5 * value), Math.Sqrt(0.5 / value) * z.ImaginaryNumber); } public static Complex Recip(Complex z) { if (z.RealNumber == 0.0 && z.ImaginaryNumber == 0.0) { Console.WriteLine("multiplicative inverse (reciprocal) not defined for complex zero"); return z; } var zr = new Complex(1.0, 0.0) { RealNumber = z.RealNumber/(z.RealNumber*z.RealNumber + z.ImaginaryNumber*z.ImaginaryNumber), ImaginaryNumber = -z.ImaginaryNumber/(z.RealNumber*z.RealNumber + z.ImaginaryNumber*z.ImaginaryNumber) }; return zr; } public Complex SetPolar(double mod, double arg) { var z = new Complex(); var t = arg; z.RealNumber = mod * Math.Cos(t); z.ImaginaryNumber = mod * Math.Sin(t); return z; } public static Complex NthRoot(Complex z, long n, long k) { var mod = z.Modulus; var arg = z.Argument; var lmod = Math.Log(mod); var rlmod = lmod / n; var rmod = Math.Exp(rlmod); var zrn = new Complex(); var t = arg / n + 2 * k * Math.PI / n; zrn.RealNumber = rmod * Math.Cos(t); zrn.ImaginaryNumber = rmod * Math.Sin(t); return zrn; } public static Complex Cos(Complex z) { var z1 = Exp(new Complex(-z.ImaginaryNumber, z.RealNumber)); var z2 = Exp(new Complex(z.ImaginaryNumber, -z.RealNumber)); return new Complex(0.5 * (z1.RealNumber + z2.RealNumber), 0.5 * (z1.ImaginaryNumber+ z2.ImaginaryNumber)); } public static Complex Cosh(Complex z) { Complex z1 = Exp(z); Complex z2 = Exp(new Complex(-z.RealNumber, -z.ImaginaryNumber)); return new Complex(0.5 * (z1.RealNumber + z2.RealNumber), 0.5 * (z1.ImaginaryNumber + z2.ImaginaryNumber)); } public static Complex Sin(Complex z) { Complex z1 = Exp(new Complex(-z.ImaginaryNumber, z.RealNumber)); Complex z2 = Exp(new Complex(z.ImaginaryNumber, -z.RealNumber)); return new Complex(0.5 * (z1.ImaginaryNumber - z2.ImaginaryNumber), 0.5 * (z2.RealNumber - z1.RealNumber)); } public static Complex Sinh(Complex z) { Complex z1 = Exp(z); Complex z2 = Exp(new Complex(-z.RealNumber, -z.ImaginaryNumber)); return new Complex(0.5 * (z1.RealNumber - z2.RealNumber), 0.5 * (z1.ImaginaryNumber - z2.ImaginaryNumber)); } public static Complex Tan(Complex z) { return Sin(z) / Cos(z); } public static Complex Tanh(Complex z) { return Sinh(z) / Cosh(z); } public static Complex Log10(Complex z) { const double log10 = 2.3025850929940459; Complex value = Log(z); value.RealNumber /= log10; value.ImaginaryNumber /= log10; return value; } public override string ToString() { return (String.Format("( {0}, {1} )", RealNumber, ImaginaryNumber)); } public override int GetHashCode() { unchecked { return (_realNumber.GetHashCode()*397) ^ _imaginaryNumber.GetHashCode(); } } public void Show() { Console.WriteLine(ToString()); } public void ShowPolar() { Console.WriteLine("{0} * e^(i * {1})", Modulus, Argument); } public string Polar() { var z = new Complex(this); var s = z.Modulus + " * e^(i * " + z.Argument + ")"; return s; } public void Dump() { Debug.WriteLine(ToString()); } public void DumpPolar() { Debug.WriteLine(string.Format("{0} * e^(i * {1})", Modulus, Argument)); } private double Truncate(double dval, int ndigs) { // MBP rounding algorithm // ndigs = number of decimal digits double rndfac = Math.Pow(10, ndigs); dval *= rndfac; dval = Math.Round(dval); dval /= rndfac; return dval; } public Complex Round(int ndigs) { var z = new Complex(this); z.RealNumber = Truncate(z.RealNumber, ndigs); z.ImaginaryNumber = Truncate(z.ImaginaryNumber, ndigs); return z; } public bool Equals(Complex other) { return _realNumber.Equals(other._realNumber) && _imaginaryNumber.Equals(other._imaginaryNumber); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; return obj is Complex && Equals((Complex)obj); } } }