2 // Complex.cs: Complex number support
5 // Miguel de Icaza (miguel@gnome.org)
6 // Marek Safar (marek.safar@gmail.com)
7 // Jb Evain (jbevain@novell.com)
9 // Copyright 2009, 2010 Novell, Inc.
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 namespace System.Numerics {
35 public struct Complex : IEquatable<Complex>, IFormattable
37 double real, imaginary;
39 public static readonly Complex ImaginaryOne = new Complex (0, 1);
40 public static readonly Complex One = new Complex (1, 0);
41 public static readonly Complex Zero = new Complex (0, 0);
43 public double Imaginary {
44 get { return imaginary; }
51 public double Magnitude {
52 get { return Math.Sqrt (imaginary * imaginary + real * real); }
56 get { return Math.Atan2 (imaginary, real); }
59 public Complex (double real, double imaginary)
61 this.imaginary = imaginary;
65 public static Complex FromPolarCoordinates (double magnitude, double phase)
67 return new Complex (magnitude * Math.Cos (phase), magnitude * Math.Sin (phase));
70 public static Complex operator + (Complex left, Complex right)
72 return new Complex (left.real + right.real, left.imaginary + right.imaginary);
75 public static Complex Add (Complex left, Complex right)
77 return new Complex (left.real + right.real, left.imaginary + right.imaginary);
80 public static Complex operator - (Complex left, Complex right)
82 return new Complex (left.real - right.real, left.imaginary - right.imaginary);
85 public static Complex Subtract (Complex left, Complex right)
87 return new Complex (left.real - right.real, left.imaginary - right.imaginary);
90 public static Complex operator * (Complex left, Complex right)
93 left.real * right.real - left.imaginary * right.imaginary,
94 left.real * right.imaginary + left.imaginary * right.real);
97 public static Complex Multiply (Complex left, Complex right)
100 left.real * right.real - left.imaginary * right.imaginary,
101 left.real * right.imaginary + left.imaginary * right.real);
104 public static Complex operator / (Complex left, Complex right)
106 double rsri = right.real * right.real + right.imaginary * right.imaginary;
108 (left.real * right.real + left.imaginary * right.imaginary) / rsri,
110 (left.imaginary * right.real - left.real * right.imaginary) / rsri);
113 public static Complex Divide (Complex dividend, Complex divisor)
115 double rsri = divisor.real * divisor.real + divisor.imaginary * divisor.imaginary;
117 (dividend.real * divisor.real + dividend.imaginary * divisor.imaginary) / rsri,
119 (dividend.imaginary * divisor.real - dividend.real * divisor.imaginary) / rsri);
122 public static bool operator == (Complex left, Complex right)
124 return left.real == right.real && left.imaginary == right.imaginary;
127 public bool Equals (Complex value)
129 return real == value.real && imaginary == value.imaginary;
132 public override bool Equals (object obj)
134 if (obj == null || !(obj is Complex))
137 Complex r = (Complex) obj;
138 return real == r.real && imaginary == r.imaginary;
141 public static bool operator != (Complex left, Complex right)
143 return left.real != right.real || left.imaginary != right.imaginary;
146 public static Complex operator - (Complex value)
148 return new Complex (-value.real, -value.imaginary);
151 public static implicit operator Complex (byte value)
153 return new Complex (value, 0);
156 public static implicit operator Complex (double value)
158 return new Complex (value, 0);
161 public static implicit operator Complex (short value)
163 return new Complex (value, 0);
166 public static implicit operator Complex (int value)
168 return new Complex (value, 0);
171 public static implicit operator Complex (long value)
173 return new Complex (value, 0);
176 [CLSCompliant (false)]
177 public static implicit operator Complex (sbyte value)
179 return new Complex (value, 0);
182 public static implicit operator Complex (float value)
184 return new Complex (value, 0);
187 [CLSCompliant (false)]
188 public static implicit operator Complex (ushort value)
190 return new Complex (value, 0);
193 [CLSCompliant (false)]
194 public static implicit operator Complex (uint value)
196 return new Complex (value, 0);
199 [CLSCompliant (false)]
200 public static implicit operator Complex (ulong value)
202 return new Complex (value, 0);
205 public static explicit operator Complex (decimal value)
207 return new Complex ((double) value, 0);
210 public static explicit operator Complex (BigInteger value)
212 return new Complex ((double) value, 0);
215 public static double Abs (Complex value)
217 return Math.Sqrt (value.imaginary * value.imaginary + value.real * value.real);
220 public static Complex Conjugate (Complex value)
222 return new Complex (value.real, -value.imaginary);
225 public static Complex Cos (Complex value)
227 return new Complex (Math.Cos (value.real) * Math.Cosh (value.imaginary),
228 -Math.Sin (value.real) * Math.Sinh (value.imaginary));
231 public static Complex Cosh (Complex value)
233 return new Complex (Math.Cosh (value.real) * Math.Cos (value.imaginary),
234 -Math.Sinh (value.real) * Math.Sin (value.imaginary));
237 public static Complex Negate (Complex value)
242 public static Complex Sin (Complex value)
244 return new Complex (Math.Sin (value.real) * Math.Cosh (value.imaginary),
245 Math.Cos (value.real) * Math.Sinh (value.imaginary));
248 public static Complex Sinh (Complex value)
250 return new Complex (Math.Sinh (value.real) * Math.Cos (value.imaginary),
251 Math.Cosh (value.real) * Math.Sin (value.imaginary));
254 public static Complex Reciprocal (Complex value)
262 public static Complex Tan (Complex value)
264 return Sin (value) / Cos (value);
267 public static Complex Tanh (Complex value)
269 return Sinh (value) / Cosh (value);
272 public static Complex Acos (Complex value)
274 return -ImaginaryOne * Log (value + (ImaginaryOne * Sqrt (One - (value * value))));
277 public static Complex Asin (Complex value)
279 return -ImaginaryOne * Log ((ImaginaryOne * value) + Sqrt (One - (value * value)));
282 public static Complex Atan (Complex value)
284 return (ImaginaryOne / new Complex (2, 0)) * (Log (One - (ImaginaryOne * value)) - Log (One + (ImaginaryOne * value)));
287 public static Complex Exp (Complex value)
289 var e = Math.Exp (value.real);
291 return new Complex (e * Math.Cos (value.imaginary), e * Math.Sin (value.imaginary));
294 public static Complex Log (Complex value)
296 return new Complex (Math.Log (Abs (value)), value.Phase);
299 public static Complex Log (Complex value, double baseValue)
301 return Log (value) / Log (new Complex (baseValue, 0));
304 public static Complex Log10 (Complex value)
306 return Log (value, 10);
309 public static Complex Sqrt (Complex value)
311 return FromPolarCoordinates (Math.Sqrt (value.Magnitude), value.Phase / 2);
314 public static Complex Pow (Complex value, double power)
316 return Pow (value, new Complex (power, 0));
319 public static Complex Pow (Complex value, Complex power)
321 return Exp (Log (value) * power);
324 public override int GetHashCode ()
326 return real.GetHashCode () ^ imaginary.GetHashCode ();
329 public override string ToString ()
331 return string.Format ("({0}, {1})", real, imaginary);
334 public string ToString (IFormatProvider provider)
336 return string.Format (provider, "({0}, {1})", real, imaginary);
339 public string ToString (string format)
341 return string.Format ("({0}, {1})", real.ToString (format), imaginary.ToString (format));
344 public string ToString (string format, IFormatProvider provider)
346 return string.Format ("({0}, {1})", real.ToString (format, provider), imaginary.ToString (format, provider));