C#で複素数

どうも必要になりそうなので構造体で複素数型を作ってみる。他に作っている人はたくさんいそうだけど、C#の復習を兼ねてやってみました。以下にソースを貼り付け。
チェックなど一切していない上にけっこう適当です。使用は自己責任で。

/// <summary>
/// 複素数
/// </summary>
public struct Complex
{
	double real;
	double imaginary;
	
	static string imaginaryUnit = "i";

	/// <summary>
	/// 複素数
	/// </summary>
	/// <param name="re">実部</param>
	/// <param name="im">虚部</param>
	public Complex( double re,double im )
	{
		real = re;
		imaginary = im;
	}

	/// <summary>
	/// 実部
	/// </summary>
	public double Real
	{
		get
		{
			return real;
		}
		set
		{
			real = value;
		}
	}

	/// <summary>
	/// 虚部
	/// </summary>
	public double Imaginary
	{
		get
		{
			return imaginary;
		}
		set
		{
			imaginary = value;
		}
	}

	/// <summary>
	/// 絶対値
	/// </summary>
	public double Abs
	{
		get
		{
			return Math.Sqrt(Abs2( this ));
		}
		set
		{
			double a = this.Arg;
			real = value * Math.Cos( a );
			imaginary = value * Math.Sin( a );
		}
	}

	/// <summary>
	/// 偏角 [rad]
	/// </summary>
	public double Arg
	{
		get
		{
			return Math.Atan2( imaginary , real );
		}
		set
		{
			double v = this.Abs;
			real = v * Math.Cos( value );
			imaginary = v * Math.Sin( value );
		}
	}

	/// <summary>
	/// 虚数単位を表す文字(デフォルトは"i")
	/// </summary>
	public static string ImaginaryUnit
	{
		get
		{
			return imaginaryUnit;
		}
		set
		{
			imaginaryUnit = value;
		}
	}

	#region 算術演算子
	#region 加算
	public static Complex operator + ( Complex x1,double x2 )
	{
		return new Complex( x1.Real + x2, x1.Imaginary );
	}

	public static Complex operator + ( double x1,Complex x2 )
	{
		return x2 + x1;
	}

	public static Complex operator + ( Complex x1,Complex x2 )
	{
		return new Complex( x1.Real + x2.Real, x1.Imaginary + x2.Imaginary );
	}
	#endregion
	#region 減算
	public static Complex operator - ( Complex x1,double x2 )
	{
		return new Complex( x1.Real - x2, x1.Imaginary );
	}

	public static Complex operator - ( double x1,Complex x2 )
	{
		return new Complex( x1 - x2.Real, x2.Imaginary );
	}

	public static Complex operator - ( Complex x1,Complex x2 )
	{
		return new Complex( x1.Real - x2.Real, x1.Real - x2.Real );
	}
	#endregion
	#region 乗算
	public static Complex operator * ( double a, Complex x1 )
	{
		return new Complex( a * x1.Real, a * x1.Imaginary );
	}

	public static Complex operator * ( Complex x1,double a )
	{
		return a * x1;
	}

	public static Complex operator * ( Complex x1,Complex x2 )
	{
		return new Complex( x1.Real * x2.Real - x1.Imaginary * x2.Imaginary,
			x1.Real * x2.Imaginary + x1.Imaginary * x2.Real );
	}
	#endregion
	#region 除算
	public static Complex operator / ( Complex x1,double a )
	{
		return new Complex( x1.Real / a, x1.Imaginary / a );
	}

	public static Complex operator / ( double a, Complex x1 )
	{
		return a * Conj(x1) / Abs2(x1);
	}

	public static Complex operator / ( Complex x1,Complex x2 )
	{
		return x1 * Conj(x2) / Abs2(x2);
	}
	#endregion
	#endregion

	#region 関係演算子
	#region 等号
	public static bool operator == ( Complex x1,double x2 )
	{
		return x1.Real == x2 && x1.Imaginary == 0;
	}

	public static bool operator == ( double x1,Complex x2 )
	{
		return x2 == x1;
	}

	public static bool operator == ( Complex x1,Complex x2 )
	{
		return x1.Real == x2.Real && x1.Imaginary == x2.Imaginary;
	}
	#endregion
	#region 不等号
	public static bool operator != ( Complex x1,double x2 )
	{
		return x1.Real != x2 || x1.Imaginary != 0;
	}

	public static bool operator != ( double x1,Complex x2 )
	{
		return x2 != x1;
	}

	public static bool operator != ( Complex x1,Complex x2 )
	{
		return x1.Real != x2.Real || x1.Imaginary != x2.Imaginary;
	}
	#endregion

	public override bool Equals(object obj)
	{
		if ( obj is Complex )
		{
			return this == (Complex)obj;
		}

		return false;
	}

	public override int GetHashCode()
	{
		// 注:かなり適当
		return real.GetHashCode() + imaginary.GetHashCode();
	}
	#endregion

	#region 関数
	/// <summary>
	/// 共役複素数
	/// </summary>
	/// <param name="x"></param>
	/// <returns></returns>
	public static Complex Conj( Complex x )
	{
		return new Complex( x.Real, -x.Imaginary );
	}

	/// <summary>
	/// 数値を文字列に変換
	/// </summary>
	/// <returns>文字列</returns>
	public override string ToString()
	{
		if ( imaginary > 0 )
		{
			return real.ToString() + " + " + imaginary.ToString() + ImaginaryUnit;
		} 
		else if ( imaginary == 0 )
		{
			return real.ToString();
		} 
		else
		{
			return real.ToString() + " - " + Math.Abs(imaginary).ToString() + ImaginaryUnit;
		}
	}

	/// <summary>
	/// 数値を極座標形式の文字列に変換
	/// </summary>
	/// <returns></returns>
	public string ToStringPolar()
	{
		return Abs + " * ( cos(" + Arg + ") + sin(" + Arg + "))";
	}
	#endregion

	#region 内部処理
	/// <summary>
	/// 絶対値の2乗
	/// </summary>
	/// <param name="x"></param>
	/// <returns></returns>
	private static double Abs2( Complex x )
	{
		return x.Real * x.Real + x.Imaginary * x.Imaginary;
	}
	#endregion
}