PageRenderTime 43ms CodeModel.GetById 15ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

/IronPython_Main/Runtime/Microsoft.Dynamic/Math/Complex64.cs

#
C# | 276 lines | 199 code | 51 blank | 26 comment | 33 complexity | 2d8cd729fce6b09722e0411c0f08b79b MD5 | raw file
  1/* ****************************************************************************
  2 *
  3 * Copyright (c) Microsoft Corporation. 
  4 *
  5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
  6 * copy of the license can be found in the License.html file at the root of this distribution. If 
  7 * you cannot locate the  Apache License, Version 2.0, please send an email to 
  8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
  9 * by the terms of the Apache License, Version 2.0.
 10 *
 11 * You must not remove this notice, or any other, from this software.
 12 *
 13 *
 14 * ***************************************************************************/
 15
 16using System;
 17using Microsoft.Scripting.Utils;
 18
 19#if !CLR2
 20using BigInt = System.Numerics.BigInteger;
 21#endif
 22
 23namespace Microsoft.Scripting.Math {
 24    /// <summary>
 25    /// Implementation of the complex number data type.
 26    /// </summary>
 27    [Serializable]
 28    public struct Complex64 {
 29        public static readonly Complex64 Zero = new Complex64(0.0, 0.0);
 30        public static readonly Complex64 One = new Complex64(1.0, 0.0);
 31        public static readonly Complex64 ImaginaryOne = new Complex64(0.0, 1.0);
 32
 33        private readonly double real, imag;
 34
 35        public static Complex64 MakeImaginary(double imag) {
 36            return new Complex64(0.0, imag);
 37        }
 38
 39        public static Complex64 MakeReal(double real) {
 40            return new Complex64(real, 0.0);
 41        }
 42
 43        public static Complex64 Make(double real, double imag) {
 44            return new Complex64(real, imag);
 45        }
 46
 47        public Complex64(double real)
 48            : this(real, 0.0) {
 49        }
 50
 51        public Complex64(double real, double imag) {
 52            this.real = real;
 53            this.imag = imag;
 54        }
 55
 56        public bool IsZero {
 57            get {
 58                return real == 0.0 && imag == 0.0;
 59            }
 60        }
 61
 62        public double Real {
 63            get {
 64                return real;
 65            }
 66        }
 67
 68        public double Imag {
 69            get {
 70                return imag;
 71            }
 72        }
 73
 74        public Complex64 Conjugate() {
 75            return new Complex64(real, -imag);
 76        }
 77
 78
 79        public override string ToString() {
 80            if (real == 0.0) return imag.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + "j";
 81            else if (imag < 0.0) return string.Format(System.Globalization.CultureInfo.InvariantCulture.NumberFormat, "({0}{1}j)", real, imag);
 82            else return string.Format(System.Globalization.CultureInfo.InvariantCulture.NumberFormat, "({0}+{1}j)", real, imag);
 83        }
 84
 85        public static implicit operator Complex64(bool b) {
 86            return b ? One : Zero;
 87        }
 88
 89        public static implicit operator Complex64(int i) {
 90            return MakeReal(i);
 91        }
 92
 93        [CLSCompliant(false)]
 94        public static implicit operator Complex64(uint i) {
 95            return MakeReal(i);
 96        }
 97
 98        public static implicit operator Complex64(short i) {
 99            return MakeReal(i);
100        }
101        
102        [CLSCompliant(false)]
103        public static implicit operator Complex64(ushort i) {
104            return MakeReal(i);
105        }
106
107        public static implicit operator Complex64(long l) {
108            return MakeReal(l);
109        }
110        [CLSCompliant(false)]
111        public static implicit operator Complex64(ulong i) {
112            return MakeReal(i);
113        }
114
115        [CLSCompliant(false)]
116        public static implicit operator Complex64(sbyte i) {
117            return MakeReal(i);
118        }
119
120        public static implicit operator Complex64(byte i) {
121            return MakeReal(i);
122        }
123
124        public static implicit operator Complex64(float f) {
125            return MakeReal(f);
126        }
127
128        public static implicit operator Complex64(double d) {
129            return MakeReal(d);
130        }
131
132        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] // TODO: fix
133        public static implicit operator Complex64(BigInteger i) {
134            ContractUtils.RequiresNotNull(i, "i");
135
136            // throws an overflow exception if we can't handle the value.
137            return MakeReal((double)i);
138        }
139
140#if !CLR2
141        public static implicit operator Complex64(BigInt i) {
142            // throws an overflow exception if we can't handle the value.
143            return MakeReal((double)i);
144        }
145#endif
146
147        public static bool operator ==(Complex64 x, Complex64 y) {
148            return x.real == y.real && x.imag == y.imag;
149        }
150
151        public static bool operator !=(Complex64 x, Complex64 y) {
152            return x.real != y.real || x.imag != y.imag;
153        }
154
155        public static Complex64 Add(Complex64 x, Complex64 y) {
156            return x + y;
157        }
158
159        public static Complex64 operator +(Complex64 x, Complex64 y) {
160            return new Complex64(x.real + y.real, x.imag + y.imag);
161        }
162
163        public static Complex64 Subtract(Complex64 x, Complex64 y) {
164            return x - y;
165        }
166
167        public static Complex64 operator -(Complex64 x, Complex64 y) {
168            return new Complex64(x.real - y.real, x.imag - y.imag);
169        }
170
171        public static Complex64 Multiply(Complex64 x, Complex64 y) {
172            return x * y;
173        }
174
175        public static Complex64 operator *(Complex64 x, Complex64 y) {
176            return new Complex64(x.real * y.real - x.imag * y.imag, x.real * y.imag + x.imag * y.real);
177        }
178
179        public static Complex64 Divide(Complex64 x, Complex64 y) {
180            return x / y;
181        }
182
183        public static Complex64 operator /(Complex64 a, Complex64 b) {
184            if (b.IsZero) {
185                throw new DivideByZeroException("complex division by zero");
186            }
187
188            double real, imag, den, r;
189
190            if (System.Math.Abs(b.real) >= System.Math.Abs(b.imag)) {
191                r = b.imag / b.real;
192                den = b.real + r * b.imag;
193                real = (a.real + a.imag * r) / den;
194                imag = (a.imag - a.real * r) / den;
195            } else {
196                r = b.real / b.imag;
197                den = b.imag + r * b.real;
198                real = (a.real * r + a.imag) / den;
199                imag = (a.imag * r - a.real) / den;
200            }
201
202            return new Complex64(real, imag);
203        }
204
205        public static Complex64 Negate(Complex64 x) {
206            return -x;
207        }
208
209        public static Complex64 operator -(Complex64 x) {
210            return new Complex64(-x.real, -x.imag);
211        }
212
213        public static Complex64 Plus(Complex64 x) {
214            return +x;
215        }
216
217        public static Complex64 operator +(Complex64 x) {
218            return x;
219        }
220        
221        [Obsolete("Deprecated - consider using MS.Scripting.Utils.MathUtils.Hypot")]
222        public static double Hypot(double x, double y) {
223            return MathUtils.Hypot(x, y);
224        }
225
226        public double Abs() {
227            return MathUtils.Hypot(real, imag);
228        }
229
230        public Complex64 Power(Complex64 y) {
231            double c = y.real;
232            double d = y.imag;
233            int power = (int)c;
234
235            if (power == c && power >= 0 && d == .0) {
236                Complex64 result = One;
237                if (power == 0) return result;
238                Complex64 factor = this;
239                while (power != 0) {
240                    if ((power & 1) != 0) {
241                        result = result * factor;
242                    }
243                    factor = factor * factor;
244                    power >>= 1;
245                }
246                return result;
247            } else if (IsZero) {
248                return y.IsZero ? One : Zero;
249            } else {
250                double a = real;
251                double b = imag;
252                double powers = a * a + b * b;
253                double arg = System.Math.Atan2(b, a);
254                double mul = System.Math.Pow(powers, c / 2) * System.Math.Exp(-d * arg);
255                double common = c * arg + .5 * d * System.Math.Log(powers);
256                return new Complex64(mul * System.Math.Cos(common), mul * System.Math.Sin(common));
257            }
258        }
259
260        public override int GetHashCode() {
261            // The Object.GetHashCode function needs to be consistent with the Object.Equals function.
262            // Languages that build on top of this may have a more flexible equality function and 
263            // so may not be able to use this hash function directly.
264            // For example, Python allows that c=Complex64(1.5, 0), f = 1.5f,  c==f.
265            // so then the hash(f) == hash(c). Since the python (and other languages) can define an arbitrary
266            // hash(float) function, the language may need to define a matching hash(complex) function for
267            // the cases where the float and complex numbers overlap.
268            return (int)real + (int)imag * 1000003;
269        }
270
271        public override bool Equals(object obj) {
272            if (!(obj is Complex64)) return false;
273            return this == ((Complex64)obj);
274        }
275    }
276}