In .:
[mono.git] / mcs / class / System.Drawing / Test / DrawingTest / Exocortex.DSP / src / Complex.cs
1 /*\r
2  * BSD Licence:\r
3  * Copyright (c) 2001, 2002 Ben Houston [ ben@exocortex.org ]\r
4  * Exocortex Technologies [ www.exocortex.org ]\r
5  * All rights reserved.\r
6  *\r
7  * Redistribution and use in source and binary forms, with or without \r
8  * modification, are permitted provided that the following conditions are met:\r
9  *\r
10  * 1. Redistributions of source code must retain the above copyright notice, \r
11  * this list of conditions and the following disclaimer.\r
12  * 2. Redistributions in binary form must reproduce the above copyright \r
13  * notice, this list of conditions and the following disclaimer in the \r
14  * documentation and/or other materials provided with the distribution.\r
15  * 3. Neither the name of the <ORGANIZATION> nor the names of its contributors\r
16  * may be used to endorse or promote products derived from this software\r
17  * without specific prior written permission.\r
18  *\r
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR\r
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
26  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT \r
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\r
29  * DAMAGE.\r
30  */\r
31 \r
32 using System;\r
33 using System.Diagnostics;\r
34 using System.Runtime.InteropServices;\r
35 \r
36 \r
37 namespace Exocortex.DSP {\r
38 \r
39         // Comments? Questions? Bugs? Tell Ben Houston at ben@exocortex.org\r
40         // Version: May 4, 2002\r
41 \r
42         /// <summary>\r
43         /// <p>A double-precision complex number representation.</p>\r
44         /// </summary>\r
45         [StructLayout(LayoutKind.Sequential)]\r
46         public struct Complex : IComparable, ICloneable {\r
47 \r
48                 //-----------------------------------------------------------------------------------\r
49                 //-----------------------------------------------------------------------------------\r
50 \r
51                 /// <summary>\r
52                 /// The real component of the complex number\r
53                 /// </summary>\r
54                 public double Re;\r
55 \r
56                 /// <summary>\r
57                 /// The imaginary component of the complex number\r
58                 /// </summary>\r
59                 public double Im;\r
60 \r
61                 //-----------------------------------------------------------------------------------\r
62                 //-----------------------------------------------------------------------------------\r
63 \r
64                 /// <summary>\r
65                 /// Create a complex number from a real and an imaginary component\r
66                 /// </summary>\r
67                 /// <param name="real"></param>\r
68                 /// <param name="imaginary"></param>\r
69                 public Complex( double real, double imaginary ) {\r
70                         this.Re         = (double) real;\r
71                         this.Im = (double) imaginary;\r
72                 }\r
73 \r
74                 /// <summary>\r
75                 /// Create a complex number based on an existing complex number\r
76                 /// </summary>\r
77                 /// <param name="c"></param>\r
78                 public Complex( Complex c ) {\r
79                         this.Re         = c.Re;\r
80                         this.Im = c.Im;\r
81                 }\r
82 \r
83                 /// <summary>\r
84                 /// Create a complex number from a real and an imaginary component\r
85                 /// </summary>\r
86                 /// <param name="real"></param>\r
87                 /// <param name="imaginary"></param>\r
88                 /// <returns></returns>\r
89                 static public Complex   FromRealImaginary( double real, double imaginary ) {\r
90                         Complex c;\r
91                         c.Re            = (double) real;\r
92                         c.Im = (double) imaginary;\r
93                         return c;\r
94                 }\r
95 \r
96                 /// <summary>\r
97                 /// Create a complex number from a modulus (length) and an argument (radian)\r
98                 /// </summary>\r
99                 /// <param name="modulus"></param>\r
100                 /// <param name="argument"></param>\r
101                 /// <returns></returns>\r
102                 static public Complex   FromModulusArgument( double modulus, double argument ) {\r
103                         Complex c;\r
104                         c.Re            = (double)( modulus * System.Math.Cos( argument ) );\r
105                         c.Im    = (double)( modulus * System.Math.Sin( argument ) );\r
106                         return c;\r
107                 }\r
108                 \r
109                 //-----------------------------------------------------------------------------------\r
110                 //-----------------------------------------------------------------------------------\r
111 \r
112                 object  ICloneable.Clone() {\r
113                         return  new Complex( this );\r
114                 }\r
115                 /// <summary>\r
116                 /// Clone the complex number\r
117                 /// </summary>\r
118                 /// <returns></returns>\r
119                 public Complex  Clone() {\r
120                         return  new Complex( this );\r
121                 }\r
122                 \r
123                 //-----------------------------------------------------------------------------------\r
124                 //-----------------------------------------------------------------------------------\r
125 \r
126                 /// <summary>\r
127                 /// The modulus (length) of the complex number\r
128                 /// </summary>\r
129                 /// <returns></returns>\r
130                 public double   GetModulus() {\r
131                         double  x       = this.Re;\r
132                         double  y       = this.Im;\r
133                         return  (double) Math.Sqrt( x*x + y*y );\r
134                 }\r
135 \r
136                 /// <summary>\r
137                 /// The squared modulus (length^2) of the complex number\r
138                 /// </summary>\r
139                 /// <returns></returns>\r
140                 public double   GetModulusSquared() {\r
141                         double  x       = this.Re;\r
142                         double  y       = this.Im;\r
143                         return  (double) x*x + y*y;\r
144                 }\r
145 \r
146                 /// <summary>\r
147                 /// The argument (radians) of the complex number\r
148                 /// </summary>\r
149                 /// <returns></returns>\r
150                 public double   GetArgument() {\r
151                         return (double) Math.Atan2( this.Im, this.Re );\r
152                 }\r
153 \r
154                 //-----------------------------------------------------------------------------------\r
155 \r
156                 /// <summary>\r
157                 /// Get the conjugate of the complex number\r
158                 /// </summary>\r
159                 /// <returns></returns>\r
160                 public Complex GetConjugate() {\r
161                         return FromRealImaginary( this.Re, -this.Im );\r
162                 }\r
163 \r
164                 //-----------------------------------------------------------------------------------\r
165 \r
166                 /// <summary>\r
167                 /// Scale the complex number to 1.\r
168                 /// </summary>\r
169                 public void Normalize() {\r
170                         double  modulus = this.GetModulus();\r
171                         if( modulus == 0 ) {\r
172                                 throw new DivideByZeroException( "Can not normalize a complex number that is zero." );\r
173                         }\r
174                         this.Re = (double)( this.Re / modulus );\r
175                         this.Im = (double)( this.Im / modulus );\r
176                 }\r
177 \r
178                 //-----------------------------------------------------------------------------------\r
179                 //-----------------------------------------------------------------------------------\r
180 \r
181                 /// <summary>\r
182                 /// Convert to a from double precision complex number to a single precison complex number\r
183                 /// </summary>\r
184                 /// <param name="cF"></param>\r
185                 /// <returns></returns>\r
186                 public static explicit operator Complex ( ComplexF cF ) {\r
187                         Complex c;\r
188                         c.Re    = (double) cF.Re;\r
189                         c.Im    = (double) cF.Im;\r
190                         return c;\r
191                 }\r
192                 \r
193                 /// <summary>\r
194                 /// Convert from a single precision real number to a complex number\r
195                 /// </summary>\r
196                 /// <param name="d"></param>\r
197                 /// <returns></returns>\r
198                 public static explicit operator Complex ( double d ) {\r
199                         Complex c;\r
200                         c.Re    = (double) d;\r
201                         c.Im    = (double) 0;\r
202                         return c;\r
203                 }\r
204 \r
205                 /// <summary>\r
206                 /// Convert from a single precision complex to a real number\r
207                 /// </summary>\r
208                 /// <param name="c"></param>\r
209                 /// <returns></returns>\r
210                 public static explicit operator double ( Complex c ) {\r
211                         return (double) c.Re;\r
212                 }\r
213                 \r
214                 //-----------------------------------------------------------------------------------\r
215                 //-----------------------------------------------------------------------------------\r
216 \r
217                 /// <summary>\r
218                 /// Are these two complex numbers equivalent?\r
219                 /// </summary>\r
220                 /// <param name="a"></param>\r
221                 /// <param name="b"></param>\r
222                 /// <returns></returns>\r
223                 public static bool      operator==( Complex a, Complex b ) {\r
224                         return  ( a.Re == b.Re ) && ( a.Im == b.Im );\r
225                 }\r
226 \r
227                 /// <summary>\r
228                 /// Are these two complex numbers different?\r
229                 /// </summary>\r
230                 /// <param name="a"></param>\r
231                 /// <param name="b"></param>\r
232                 /// <returns></returns>\r
233                 public static bool      operator!=( Complex a, Complex b ) {\r
234                         return  ( a.Re != b.Re ) || ( a.Im != b.Im );\r
235                 }\r
236 \r
237                 /// <summary>\r
238                 /// Get the hash code of the complex number\r
239                 /// </summary>\r
240                 /// <returns></returns>\r
241                 public override int             GetHashCode() {\r
242                         return  ( this.Re.GetHashCode() ^ this.Im.GetHashCode() );\r
243                 }\r
244 \r
245                 /// <summary>\r
246                 /// Is this complex number equivalent to another object?\r
247                 /// </summary>\r
248                 /// <param name="o"></param>\r
249                 /// <returns></returns>\r
250                 public override bool    Equals( object o ) {\r
251                         if( o is Complex ) {\r
252                                 Complex c = (Complex) o;\r
253                                 return   ( this == c );\r
254                         }\r
255                         return  false;\r
256                 }\r
257 \r
258                 //-----------------------------------------------------------------------------------\r
259                 //-----------------------------------------------------------------------------------\r
260 \r
261                 /// <summary>\r
262                 /// Compare to other complex numbers or real numbers\r
263                 /// </summary>\r
264                 /// <param name="o"></param>\r
265                 /// <returns></returns>\r
266                 public int      CompareTo( object o ) {\r
267                         if( o == null ) {\r
268                                 return 1;  // null sorts before current\r
269                         }\r
270                         if( o is Complex ) {\r
271                                 return  this.GetModulus().CompareTo( ((Complex)o).GetModulus() );\r
272                         }\r
273                         if( o is double ) {\r
274                                 return  this.GetModulus().CompareTo( (double)o );\r
275                         }\r
276                         if( o is ComplexF ) {\r
277                                 return  this.GetModulus().CompareTo( ((ComplexF)o).GetModulus() );\r
278                         }\r
279                         if( o is float ) {\r
280                                 return  this.GetModulus().CompareTo( (float)o );\r
281                         }\r
282                         throw new ArgumentException();\r
283                 }\r
284 \r
285                 //-----------------------------------------------------------------------------------\r
286                 //-----------------------------------------------------------------------------------\r
287 \r
288                 /// <summary>\r
289                 /// This operator doesn't do much. :-)\r
290                 /// </summary>\r
291                 /// <param name="a"></param>\r
292                 /// <returns></returns>\r
293                 public static Complex operator+( Complex a ) {\r
294                         return a;\r
295                 }\r
296 \r
297                 /// <summary>\r
298                 /// Negate the complex number\r
299                 /// </summary>\r
300                 /// <param name="a"></param>\r
301                 /// <returns></returns>\r
302                 public static Complex operator-( Complex a ) {\r
303                         a.Re    = -a.Re;\r
304                         a.Im    = -a.Im;\r
305                         return a;\r
306                 }\r
307 \r
308                 /// <summary>\r
309                 /// Add a complex number to a real\r
310                 /// </summary>\r
311                 /// <param name="a"></param>\r
312                 /// <param name="f"></param>\r
313                 /// <returns></returns>\r
314                 public static Complex operator+( Complex a, double f ) {\r
315                         a.Re    = (double)( a.Re + f );\r
316                         return a;\r
317                 }\r
318 \r
319                 /// <summary>\r
320                 /// Add a real to a complex number\r
321                 /// </summary>\r
322                 /// <param name="f"></param>\r
323                 /// <param name="a"></param>\r
324                 /// <returns></returns>\r
325                 public static Complex operator+( double f, Complex a ) {\r
326                         a.Re    = (double)( a.Re + f );\r
327                         return a;\r
328                 }\r
329 \r
330                 /// <summary>\r
331                 /// Add to complex numbers\r
332                 /// </summary>\r
333                 /// <param name="a"></param>\r
334                 /// <param name="b"></param>\r
335                 /// <returns></returns>\r
336                 public static Complex operator+( Complex a, Complex b ) {\r
337                         a.Re    = a.Re + b.Re;\r
338                         a.Im    = a.Im + b.Im;\r
339                         return a;\r
340                 }\r
341 \r
342                 /// <summary>\r
343                 /// Subtract a real from a complex number\r
344                 /// </summary>\r
345                 /// <param name="a"></param>\r
346                 /// <param name="f"></param>\r
347                 /// <returns></returns>\r
348                 public static Complex operator-( Complex a, double f ) {\r
349                         a.Re    = (double)( a.Re - f );\r
350                         return a;\r
351                 }\r
352 \r
353                 /// <summary>\r
354                 /// Subtract a complex number from a real\r
355                 /// </summary>\r
356                 /// <param name="f"></param>\r
357                 /// <param name="a"></param>\r
358                 /// <returns></returns>\r
359                 public static Complex operator-( double f, Complex a ) {\r
360                         a.Re    = (float)( f - a.Re );\r
361                         a.Im    = (float)( 0 - a.Im );\r
362                         return a;\r
363                 }\r
364 \r
365                 /// <summary>\r
366                 /// Subtract two complex numbers\r
367                 /// </summary>\r
368                 /// <param name="a"></param>\r
369                 /// <param name="b"></param>\r
370                 /// <returns></returns>\r
371                 public static Complex operator-( Complex a, Complex b ) {\r
372                         a.Re    = a.Re - b.Re;\r
373                         a.Im    = a.Im - b.Im;\r
374                         return a;\r
375                 }\r
376 \r
377                 /// <summary>\r
378                 /// Multiply a complex number by a real\r
379                 /// </summary>\r
380                 /// <param name="a"></param>\r
381                 /// <param name="f"></param>\r
382                 /// <returns></returns>\r
383                 public static Complex operator*( Complex a, double f ) {\r
384                         a.Re    = (double)( a.Re * f );\r
385                         a.Im    = (double)( a.Im * f );\r
386                         return a;\r
387                 }\r
388                 \r
389                 /// <summary>\r
390                 /// Multiply a real by a complex number\r
391                 /// </summary>\r
392                 /// <param name="f"></param>\r
393                 /// <param name="a"></param>\r
394                 /// <returns></returns>\r
395                 public static Complex operator*( double f, Complex a ) {\r
396                         a.Re    = (double)( a.Re * f );\r
397                         a.Im    = (double)( a.Im * f );\r
398                         \r
399                         return a;\r
400                 }\r
401                 \r
402                 /// <summary>\r
403                 /// Multiply two complex numbers together\r
404                 /// </summary>\r
405                 /// <param name="a"></param>\r
406                 /// <param name="b"></param>\r
407                 /// <returns></returns>\r
408                 public static Complex operator*( Complex a, Complex b ) {\r
409                         // (x + yi)(u + vi) = (xu \96 yv) + (xv + yu)i. \r
410                         double  x = a.Re, y = a.Im;\r
411                         double  u = b.Re, v = b.Im;\r
412                         \r
413                         a.Re    = (double)( x*u - y*v );\r
414                         a.Im    = (double)( x*v + y*u );\r
415                         \r
416                         return a;\r
417                 }\r
418 \r
419                 /// <summary>\r
420                 /// Divide a complex number by a real number\r
421                 /// </summary>\r
422                 /// <param name="a"></param>\r
423                 /// <param name="f"></param>\r
424                 /// <returns></returns>\r
425                 public static Complex operator/( Complex a, double f ) {\r
426                         if( f == 0 ) {\r
427                                 throw new DivideByZeroException();\r
428                         }\r
429                         \r
430                         a.Re    = (double)( a.Re / f );\r
431                         a.Im    = (double)( a.Im / f );\r
432                         \r
433                         return a;\r
434                 }\r
435                 \r
436                 /// <summary>\r
437                 /// Divide a complex number by a complex number\r
438                 /// </summary>\r
439                 /// <param name="a"></param>\r
440                 /// <param name="b"></param>\r
441                 /// <returns></returns>\r
442                 public static Complex operator/( Complex a, Complex b ) {\r
443                         double  x = a.Re,       y = a.Im;\r
444                         double  u = b.Re,       v = b.Im;\r
445                         double  denom = u*u + v*v;\r
446 \r
447                         if( denom == 0 ) {\r
448                                 throw new DivideByZeroException();\r
449                         }\r
450 \r
451                         a.Re    = (double)( ( x*u + y*v ) / denom );\r
452                         a.Im    = (double)( ( y*u - x*v ) / denom );\r
453                         \r
454                         return a;\r
455                 }\r
456 \r
457                 /// <summary>\r
458                 /// Parse a complex representation in this fashion: "( %f, %f )"\r
459                 /// </summary>\r
460                 /// <param name="s"></param>\r
461                 /// <returns></returns>\r
462                 static public Complex Parse( string s ) {\r
463                         throw new NotImplementedException( "Complex Complex.Parse( string s ) is not implemented." );\r
464                 }\r
465                 \r
466                 /// <summary>\r
467                 /// Get the string representation\r
468                 /// </summary>\r
469                 /// <returns></returns>\r
470                 public override string ToString() {\r
471                         return  String.Format( "( {0}, {1}i )", this.Re, this.Im );\r
472                 }\r
473 \r
474                 //-----------------------------------------------------------------------------------\r
475                 //-----------------------------------------------------------------------------------\r
476 \r
477                 /// <summary>\r
478                 /// Determine whether two complex numbers are almost (i.e. within the tolerance) equivalent.\r
479                 /// </summary>\r
480                 /// <param name="a"></param>\r
481                 /// <param name="b"></param>\r
482                 /// <param name="tolerance"></param>\r
483                 /// <returns></returns>\r
484                 static public bool IsEqual( Complex a, Complex b, double tolerance ) {\r
485                         return\r
486                                 ( Math.Abs( a.Re - b.Re ) < tolerance ) &&\r
487                                 ( Math.Abs( a.Im - b.Im ) < tolerance );\r
488 \r
489                 }\r
490                 \r
491                 //----------------------------------------------------------------------------------\r
492                 //----------------------------------------------------------------------------------\r
493 \r
494                 /// <summary>\r
495                 /// Represents zero\r
496                 /// </summary>\r
497                 static public Complex   Zero {\r
498                         get     {       return  new Complex( 0, 0 );    }\r
499                 }\r
500 \r
501                 /// <summary>\r
502                 /// Represents the result of sqrt( -1 )\r
503                 /// </summary>\r
504                 static public Complex   I {\r
505                         get {   return  new Complex( 0, 1 );    }\r
506                 }\r
507 \r
508                 /// <summary>\r
509                 /// Represents the largest possible value of Complex.\r
510                 /// </summary>\r
511                 static public Complex   MaxValue {\r
512                         get {   return  new Complex( double.MaxValue, double.MaxValue );        }\r
513                 }\r
514 \r
515                 /// <summary>\r
516                 /// Represents the smallest possible value of Complex.\r
517                 /// </summary>\r
518                 static public Complex   MinValue {\r
519                         get {   return  new Complex( double.MinValue, double.MinValue );        }\r
520                 }\r
521 \r
522 \r
523                 //----------------------------------------------------------------------------------\r
524                 //----------------------------------------------------------------------------------\r
525         }\r
526 \r
527 }\r