Welcome to mirror list, hosted at ThFree Co, Russian Federation.

Complex.cs « Numerics « System « System.Numerics « referencesource « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ce88cda7498d93383e91446811c5ef9156ed5b41 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
/*=========================================================================
**
** Class: Complex
**
**
** Purpose: 
** This feature is intended to create Complex Number as a type 
** that can be a part of the .NET framework (base class libraries).  
** A complex number z is a number of the form z = x + yi, where x and y 
** are real numbers, and i is the imaginary unit, with the property i2= -1.
**
**
===========================================================================*/

using System;
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;

namespace System.Numerics {

#if !SILVERLIGHT
    [Serializable]
#endif // !SILVERLIGHT
    public struct Complex : IEquatable<Complex>, IFormattable {

        // --------------SECTION: Private Data members ----------- //

        private Double m_real;
        private Double m_imaginary;

        // ---------------SECTION: Necessary Constants ----------- //

        private const Double LOG_10_INV = 0.43429448190325;


        // --------------SECTION: Public Properties -------------- //

        public Double Real {
            get {
                return m_real;
            }
        }

        public Double Imaginary {
            get {
                return m_imaginary;
            }
        }

        public Double Magnitude {
            get {
                return Complex.Abs(this);
            }
        }

        public Double Phase {
            get {
                return Math.Atan2(m_imaginary, m_real);
            }
        }

        // --------------SECTION: Attributes -------------- //

        public static readonly Complex Zero = new Complex(0.0, 0.0);
        public static readonly Complex One = new Complex(1.0, 0.0);
        public static readonly Complex ImaginaryOne = new Complex(0.0, 1.0);

        // --------------SECTION: Constructors and factory methods -------------- //

        public Complex(Double real, Double imaginary)  /* Constructor to create a complex number with rectangular co-ordinates  */
        {
            this.m_real = real;
            this.m_imaginary = imaginary;
        }

        public static Complex FromPolarCoordinates(Double magnitude, Double phase) /* Factory method to take polar inputs and create a Complex object */
        {
            return new Complex((magnitude * Math.Cos(phase)), (magnitude * Math.Sin(phase)));
        }

        public static Complex Negate(Complex value) {
            return -value;
        }

        public static Complex Add(Complex left, Complex right) {
            return left + right;
        }

        public static Complex Subtract(Complex left, Complex right) {
            return left - right;
        }

        public static Complex Multiply(Complex left, Complex right) {
            return left * right;
        }

        public static Complex Divide(Complex dividend, Complex divisor) {
            return dividend / divisor;
        }

        // --------------SECTION: Arithmetic Operator(unary) Overloading -------------- //
        public static Complex operator -(Complex value)  /* Unary negation of a complex number */
        {

            return (new Complex((-value.m_real), (-value.m_imaginary)));
        }

        // --------------SECTION: Arithmetic Operator(binary) Overloading -------------- //       
        public static Complex operator +(Complex left, Complex right) {
            return (new Complex((left.m_real + right.m_real), (left.m_imaginary + right.m_imaginary)));

        }

        public static Complex operator -(Complex left, Complex right) {
            return (new Complex((left.m_real - right.m_real), (left.m_imaginary - right.m_imaginary)));
        }

        public static Complex operator *(Complex left, Complex right) {
            // Multiplication:  (a + bi)(c + di) = (ac -bd) + (bc + ad)i
            Double result_Realpart = (left.m_real * right.m_real) - (left.m_imaginary * right.m_imaginary);
            Double result_Imaginarypart = (left.m_imaginary * right.m_real) + (left.m_real * right.m_imaginary);
            return (new Complex(result_Realpart, result_Imaginarypart));
        }

        public static Complex operator /(Complex left, Complex right) {
            // Division : Smith's formula.
            double a = left.m_real;
            double b = left.m_imaginary;
            double c = right.m_real;
            double d = right.m_imaginary;

            if (Math.Abs(d) < Math.Abs(c)) {
                double doc = d / c;
                return new Complex((a + b * doc) / (c + d * doc), (b - a * doc) / (c + d * doc));
            } else {
                double cod = c / d;
                return new Complex((b + a * cod) / (d + c * cod), (-a + b * cod) / (d + c * cod));
            }
        }


        // --------------SECTION: Other arithmetic operations  -------------- //

        public static Double Abs(Complex value) {

            if(Double.IsInfinity(value.m_real) || Double.IsInfinity(value.m_imaginary)) {
                return double.PositiveInfinity;
            }

            // |value| == sqrt(a^2 + b^2)
            // sqrt(a^2 + b^2) == a/a * sqrt(a^2 + b^2) = a * sqrt(a^2/a^2 + b^2/a^2)
            // Using the above we can factor out the square of the larger component to dodge overflow.


            double c = Math.Abs(value.m_real);
            double d = Math.Abs(value.m_imaginary);

            if (c > d) {
                double r = d / c;
                return c * Math.Sqrt(1.0 + r * r);
            } else if (d == 0.0) {
                return c;  // c is either 0.0 or NaN
            } else {
                double r = c / d;
                return d * Math.Sqrt(1.0 + r * r);
            }
        }
        public static Complex Conjugate(Complex value) {
            // Conjugate of a Complex number: the conjugate of x+i*y is x-i*y 

            return (new Complex(value.m_real, (-value.m_imaginary)));

        }
        public static Complex Reciprocal(Complex value) {
            // Reciprocal of a Complex number : the reciprocal of x+i*y is 1/(x+i*y)
            if ((value.m_real == 0) && (value.m_imaginary == 0)) {
                return Complex.Zero;
            }

            return Complex.One / value;
        }

        // --------------SECTION: Comparison Operator(binary) Overloading -------------- //

        public static bool operator ==(Complex left, Complex right) {
            return ((left.m_real == right.m_real) && (left.m_imaginary == right.m_imaginary));


        }
        public static bool operator !=(Complex left, Complex right) {
            return ((left.m_real != right.m_real) || (left.m_imaginary != right.m_imaginary));

        }

        // --------------SECTION: Comparison operations (methods implementing IEquatable<ComplexNumber>,IComparable<ComplexNumber>) -------------- //

        public override bool Equals(object obj) {
            if (!(obj is Complex)) return false;
            return this == ((Complex)obj);
        }
        public bool Equals(Complex value) {
            return ((this.m_real.Equals(value.m_real)) && (this.m_imaginary.Equals(value.m_imaginary)));

        }

        // --------------SECTION: Type-casting basic numeric data-types to ComplexNumber  -------------- //

        public static implicit operator Complex(Int16 value) {
            return (new Complex(value, 0.0));
        }
        public static implicit operator Complex(Int32 value) {
            return (new Complex(value, 0.0));
        }
        public static implicit operator Complex(Int64 value) {
            return (new Complex(value, 0.0));
        }
        [CLSCompliant(false)]
        public static implicit operator Complex(UInt16 value) {
            return (new Complex(value, 0.0));
        }
        [CLSCompliant(false)]
        public static implicit operator Complex(UInt32 value) {
            return (new Complex(value, 0.0));
        }
        [CLSCompliant(false)]
        public static implicit operator Complex(UInt64 value) {
            return (new Complex(value, 0.0));
        }
        [CLSCompliant(false)]
        public static implicit operator Complex(SByte value) {
            return (new Complex(value, 0.0));
        }
        public static implicit operator Complex(Byte value) {
            return (new Complex(value, 0.0));
        }
        public static implicit operator Complex(Single value) {
            return (new Complex(value, 0.0));
        }
        public static implicit operator Complex(Double value) {
            return (new Complex(value, 0.0));
        }
        public static explicit operator Complex(BigInteger value) {
            return (new Complex((Double)value, 0.0));
        }
        public static explicit operator Complex(Decimal value) {
            return (new Complex((Double)value, 0.0));
        }


        // --------------SECTION: Formattig/Parsing options  -------------- //

        public override String ToString() {
            return (String.Format(CultureInfo.CurrentCulture, "({0}, {1})", this.m_real, this.m_imaginary));
        }

        public String ToString(String format) {
            return (String.Format(CultureInfo.CurrentCulture, "({0}, {1})", this.m_real.ToString(format, CultureInfo.CurrentCulture), this.m_imaginary.ToString(format, CultureInfo.CurrentCulture)));
        }

        public String ToString(IFormatProvider provider) {
            return (String.Format(provider, "({0}, {1})", this.m_real, this.m_imaginary));
        }

        public String ToString(String format, IFormatProvider provider) {
            return (String.Format(provider, "({0}, {1})", this.m_real.ToString(format, provider), this.m_imaginary.ToString(format, provider)));
        }


        public override Int32 GetHashCode() {
            Int32 n1 = 99999997;
            Int32 hash_real = this.m_real.GetHashCode() % n1;
            Int32 hash_imaginary = this.m_imaginary.GetHashCode();
            Int32 final_hashcode = hash_real ^ hash_imaginary;
            return (final_hashcode);
        }



        // --------------SECTION: Trigonometric operations (methods implementing ITrigonometric)  -------------- //

        public static Complex Sin(Complex value) {
            double a = value.m_real;
            double b = value.m_imaginary;
            return new Complex(Math.Sin(a) * Math.Cosh(b), Math.Cos(a) * Math.Sinh(b));
        }

        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sinh", Justification = "Microsoft: Existing Name")]
        public static Complex Sinh(Complex value) /* Hyperbolic sin */
        {
            double a = value.m_real;
            double b = value.m_imaginary;
            return new Complex(Math.Sinh(a) * Math.Cos(b), Math.Cosh(a) * Math.Sin(b));

        }
        public static Complex Asin(Complex value) /* Arcsin */
        {
	    if ((value.m_imaginary == 0 && value.m_real < 0) || value.m_imaginary > 0)
            {
                return -Asin(-value);
            }
            return (-ImaginaryOne) * Log(ImaginaryOne * value + Sqrt(One - value * value));
        }

        public static Complex Cos(Complex value) {
            double a = value.m_real;
            double b = value.m_imaginary;
            return new Complex(Math.Cos(a) * Math.Cosh(b), - (Math.Sin(a) * Math.Sinh(b)));
        }

        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Cosh", Justification = "Microsoft: Existing Name")]
        public static Complex Cosh(Complex value) /* Hyperbolic cos */
        {
            double a = value.m_real;
            double b = value.m_imaginary;
            return new Complex(Math.Cosh(a) * Math.Cos(b), Math.Sinh(a) * Math.Sin(b));
        }
        public static Complex Acos(Complex value) /* Arccos */
        {
            if ((value.m_imaginary == 0 && value.m_real > 0) || value.m_imaginary < 0)
            {
                return System.Math.PI - Acos(-value);
            }
            return (-ImaginaryOne) * Log(value + ImaginaryOne*Sqrt(One - (value * value)));

        }
        public static Complex Tan(Complex value) {
            return (Sin(value) / Cos(value));
        }

        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Tanh", Justification = "Microsoft: Existing Name")]
        public static Complex Tanh(Complex value) /* Hyperbolic tan */
        {
            return (Sinh(value) / Cosh(value));
        }
        public static Complex Atan(Complex value) /* Arctan */
        {
            Complex Two = new Complex(2.0, 0.0);
            return (ImaginaryOne / Two) * (Log(One - ImaginaryOne * value) - Log(One + ImaginaryOne * value));
        }

        // --------------SECTION: Other numerical functions  -------------- //        

        public static Complex Log(Complex value) /* Log of the complex number value to the base of 'e' */
        {
            return (new Complex((Math.Log(Abs(value))), (Math.Atan2(value.m_imaginary, value.m_real))));

        }
        public static Complex Log(Complex value, Double baseValue) /* Log of the complex number to a the base of a double */
        {
            return (Log(value) / Log(baseValue));
        }
        public static Complex Log10(Complex value) /* Log to the base of 10 of the complex number */
        {

            Complex temp_log = Log(value);
            return (Scale(temp_log, (Double)LOG_10_INV));

        }
        public static Complex Exp(Complex value) /* The complex number raised to e */
        {
            Double temp_factor = Math.Exp(value.m_real);
            Double result_re = temp_factor * Math.Cos(value.m_imaginary);
            Double result_im = temp_factor * Math.Sin(value.m_imaginary);
            return (new Complex(result_re, result_im));
        }

        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sqrt", Justification = "Microsoft: Existing Name")]
        public static Complex Sqrt(Complex value) /* Square root ot the complex number */
        {
            return Complex.FromPolarCoordinates(Math.Sqrt(value.Magnitude), value.Phase / 2.0);
        }

        public static Complex Pow(Complex value, Complex power) /* A complex number raised to another complex number */
        {

            if (power == Complex.Zero) {
                return Complex.One;
            }

            if (value == Complex.Zero) {
                return Complex.Zero;
            }

            double a = value.m_real;
            double b = value.m_imaginary;
            double c = power.m_real;
            double d = power.m_imaginary;

            double rho = Complex.Abs(value);
            double theta = Math.Atan2(b, a);
            double newRho = c * theta + d * Math.Log(rho);

            double t = Math.Pow(rho, c) * Math.Pow(Math.E, -d * theta);

            return new Complex(t * Math.Cos(newRho), t * Math.Sin(newRho));
        }

        public static Complex Pow(Complex value, Double power) // A complex number raised to a real number 
        {
            return Pow(value, new Complex(power, 0));
        }



        //--------------- SECTION: Private member functions for internal use -----------------------------------//

        private static Complex Scale(Complex value, Double factor) {

            Double result_re = factor * value.m_real;
            Double result_im = factor * value.m_imaginary;
            return (new Complex(result_re, result_im));
        }

    }
}