Add unit test for AggregateException.GetBaseException that works on .net but is broke...
[mono.git] / mcs / class / System.Numerics / System.Numerics / Complex.cs
1 //
2 // Complex.cs: Complex number support
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@gnome.org)
6 //   Marek Safar (marek.safar@gmail.com)
7 //   Jb Evain (jbevain@novell.com)
8 //
9 // Copyright 2009, 2010 Novell, Inc.
10 //
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:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
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.
29 //
30
31 using System;
32
33 namespace System.Numerics {
34
35         public struct Complex : IEquatable<Complex>, IFormattable
36         {
37                 double real, imaginary;
38
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);
42
43                 public double Imaginary {
44                         get { return imaginary; }
45                 }
46
47                 public double Real {
48                         get { return real; }
49                 }
50
51                 public double Magnitude {
52                         get { return Math.Sqrt (imaginary * imaginary + real * real); }
53                 }
54
55                 public double Phase {
56                         get { return Math.Atan2 (imaginary, real); }
57                 }
58                 
59                 public Complex (double real, double imaginary)
60                 {
61                         this.imaginary = imaginary;
62                         this.real = real;
63                 }
64
65                 public static Complex FromPolarCoordinates (double magnitude, double phase)
66                 {
67                         return new Complex (magnitude * Math.Cos (phase), magnitude * Math.Sin (phase));
68                 }
69
70                 public static Complex operator + (Complex left, Complex right)
71                 {
72                         return new Complex (left.real + right.real, left.imaginary + right.imaginary);
73                 }
74
75                 public static Complex Add (Complex left, Complex right)
76                 {
77                         return new Complex (left.real + right.real, left.imaginary + right.imaginary);
78                 }
79                 
80                 public static Complex operator - (Complex left, Complex right)
81                 {
82                         return new Complex (left.real - right.real, left.imaginary - right.imaginary);
83                 }
84
85                 public static Complex Subtract (Complex left, Complex right)
86                 {
87                         return new Complex (left.real - right.real, left.imaginary - right.imaginary);
88                 }
89                 
90                 public static Complex operator * (Complex left, Complex right)
91                 {
92                         return new Complex (
93                                 left.real * right.real - left.imaginary * right.imaginary,
94                                 left.real * right.imaginary + left.imaginary * right.real);
95                 }
96
97                 public static Complex Multiply (Complex left, Complex right)
98                 {
99                         return new Complex (
100                                 left.real * right.real - left.imaginary * right.imaginary,
101                                 left.real * right.imaginary + left.imaginary * right.real);
102                 }
103
104                 public static Complex operator / (Complex left, Complex right)
105                 {
106                         double rsri = right.real * right.real + right.imaginary * right.imaginary;
107                         return new Complex (
108                                 (left.real * right.real + left.imaginary * right.imaginary) / rsri,
109
110                                 (left.imaginary * right.real - left.real * right.imaginary) / rsri);
111                 }
112
113                 public static Complex Divide (Complex dividend, Complex divisor)
114                 {
115                         double rsri = divisor.real * divisor.real + divisor.imaginary * divisor.imaginary;
116                         return new Complex (
117                                 (dividend.real * divisor.real + dividend.imaginary * divisor.imaginary) / rsri,
118
119                                 (dividend.imaginary * divisor.real - dividend.real * divisor.imaginary) / rsri);
120                 }
121
122                 public static bool operator == (Complex left, Complex right)
123                 {
124                         return left.real == right.real && left.imaginary == right.imaginary;
125                 }
126
127                 public bool Equals (Complex value)
128                 {
129                         return real == value.real && imaginary == value.imaginary;
130                 }
131
132                 public override bool Equals (object obj)
133                 {
134                         if (obj == null || !(obj is Complex))
135                                 return false;
136
137                         Complex r = (Complex) obj;
138                         return real == r.real && imaginary == r.imaginary;
139                 }
140                 
141                 public static bool operator != (Complex left, Complex right)
142                 {
143                         return left.real != right.real || left.imaginary != right.imaginary;
144                 }
145                 
146                 public static Complex operator - (Complex value)
147                 {
148                         return new Complex (-value.real, -value.imaginary);
149                 }
150
151                 public static implicit operator Complex (byte value)
152                 {
153                         return new Complex (value, 0);
154                 }
155
156                 public static implicit operator Complex (double value)
157                 {
158                         return new Complex (value, 0);
159                 }
160                 
161                 public static implicit operator Complex (short value)
162                 {
163                         return new Complex (value, 0);
164                 }
165                 
166                 public static implicit operator Complex (int value)
167                 {
168                         return new Complex (value, 0);
169                 }
170                 
171                 public static implicit operator Complex (long value)
172                 {
173                         return new Complex (value, 0);
174                 }
175
176                 [CLSCompliant (false)]
177                 public static implicit operator Complex (sbyte value)
178                 {
179                         return new Complex (value, 0);
180                 }
181
182                 public static implicit operator Complex (float value)
183                 {
184                         return new Complex (value, 0);
185                 }
186
187                 [CLSCompliant (false)]
188                 public static implicit operator Complex (ushort value)
189                 {
190                         return new Complex (value, 0);
191                 }
192
193                 [CLSCompliant (false)]
194                 public static implicit operator Complex (uint value)
195                 {
196                         return new Complex (value, 0);
197                 }
198
199                 [CLSCompliant (false)]
200                 public static implicit operator Complex (ulong value)
201                 {
202                         return new Complex (value, 0);
203                 }
204
205                 public static explicit operator Complex (decimal value)
206                 {
207                         return new Complex ((double) value, 0);
208                 }
209
210                 public static explicit operator Complex (BigInteger value)
211                 {
212                         return new Complex ((double) value, 0);
213                 }
214
215                 public static double Abs (Complex value)
216                 {
217                         return Math.Sqrt (value.imaginary * value.imaginary + value.real * value.real);
218                 }
219                 
220                 public static Complex Conjugate (Complex value)
221                 {
222                         return new Complex (value.real, -value.imaginary);
223                 }
224
225                 public static Complex Cos (Complex value)
226                 {
227                         return new Complex (Math.Cos (value.real) * Math.Cosh (value.imaginary),
228                                             -Math.Sin (value.real)  * Math.Sinh (value.imaginary));
229                 }
230
231                 public static Complex Cosh (Complex value)
232                 {
233                         return new Complex (Math.Cosh (value.real) * Math.Cos (value.imaginary),
234                                             -Math.Sinh (value.real)  * Math.Sin (value.imaginary));
235                 }
236                 
237                 public static Complex Negate (Complex value)
238                 {
239                         return -value;
240                 }
241
242                 public static Complex Sin (Complex value)
243                 {
244                         return new Complex (Math.Sin (value.real) * Math.Cosh (value.imaginary),
245                                             Math.Cos (value.real)  * Math.Sinh (value.imaginary));
246                 }
247                 
248                 public static Complex Sinh (Complex value)
249                 {
250                         return new Complex (Math.Sinh (value.real) * Math.Cos (value.imaginary),
251                                             Math.Cosh (value.real)  * Math.Sin (value.imaginary));
252                 }
253                 
254                 public static Complex Reciprocal (Complex value)
255                 {
256                         if (value == Zero)
257                                 return value;
258                                 
259                         return One / value;
260                 }
261                 
262                 public static Complex Tan (Complex value)
263                 {
264                         return Sin (value) / Cos (value);
265                 }
266                 
267                 public static Complex Tanh (Complex value)
268                 {
269                         return Sinh (value) / Cosh (value);
270                 }
271
272                 public static Complex Acos (Complex value)
273                 {
274                         return -ImaginaryOne * Log (value + (ImaginaryOne * Sqrt (One - (value * value))));
275                 }
276
277                 public static Complex Asin (Complex value)
278                 {
279                         return -ImaginaryOne * Log ((ImaginaryOne * value) + Sqrt (One - (value * value)));
280                 }
281
282                 public static Complex Atan (Complex value)
283                 {
284                         return (ImaginaryOne / new Complex (2, 0)) * (Log (One - (ImaginaryOne * value)) - Log (One + (ImaginaryOne * value)));
285                 }
286
287                 public static Complex Exp (Complex value)
288                 {
289                         var e = Math.Exp (value.real);
290
291                         return new Complex (e * Math.Cos (value.imaginary), e * Math.Sin (value.imaginary));
292                 }
293
294                 public static Complex Log (Complex value)
295                 {
296                         return new Complex (Math.Log (Abs (value)), value.Phase);
297                 }
298
299                 public static Complex Log (Complex value, double baseValue)
300                 {
301                         return Log (value) / Log (new Complex (baseValue, 0));
302                 }
303
304                 public static Complex Log10 (Complex value)
305                 {
306                         return Log (value, 10);
307                 }
308
309                 public static Complex Sqrt (Complex value)
310                 {
311                         return FromPolarCoordinates (Math.Sqrt (value.Magnitude), value.Phase / 2);
312                 }
313
314                 public static Complex Pow (Complex value, double power)
315                 {
316                         return Pow (value, new Complex (power, 0));
317                 }
318
319                 public static Complex Pow (Complex value, Complex power)
320                 {
321                         return Exp (Log (value) * power);
322                 }
323
324                 public override int GetHashCode ()
325                 {
326                         return real.GetHashCode () ^ imaginary.GetHashCode ();
327                 }
328
329                 public override string ToString ()
330                 {
331                         return string.Format ("({0}, {1})", real, imaginary);
332                 }
333
334                 public string ToString (IFormatProvider provider)
335                 {
336                         return string.Format (provider, "({0}, {1})", real, imaginary);
337                 }
338
339                 public string ToString (string format)
340                 {
341                         return string.Format ("({0}, {1})", real.ToString (format), imaginary.ToString (format));
342                 }
343
344                 public string ToString (string format, IFormatProvider provider)
345                 {
346                         return string.Format ("({0}, {1})", real.ToString (format, provider), imaginary.ToString (format, provider));
347                 }
348         }
349 }