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);
}
}
}