/Runtime/Microsoft.Dynamic/Math/Complex64.cs
C# | 276 lines | 199 code | 51 blank | 26 comment | 33 complexity | 5cf5b520cfc0e1ddfd82d1c473b170f1 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
- /* ****************************************************************************
- *
- * Copyright (c) Microsoft Corporation.
- *
- * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
- * copy of the license can be found in the License.html file at the root of this distribution. If
- * you cannot locate the Apache License, Version 2.0, please send an email to
- * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
- * by the terms of the Apache License, Version 2.0.
- *
- * You must not remove this notice, or any other, from this software.
- *
- *
- * ***************************************************************************/
- using System;
- using Microsoft.Scripting.Utils;
- #if FEATURE_NUMERICS
- using BigInt = System.Numerics.BigInteger;
- #endif
- namespace Microsoft.Scripting.Math {
- /// <summary>
- /// Implementation of the complex number data type.
- /// </summary>
- [Serializable]
- public struct Complex64 {
- public static readonly Complex64 Zero = new Complex64(0.0, 0.0);
- public static readonly Complex64 One = new Complex64(1.0, 0.0);
- public static readonly Complex64 ImaginaryOne = new Complex64(0.0, 1.0);
- private readonly double real, imag;
- public static Complex64 MakeImaginary(double imag) {
- return new Complex64(0.0, imag);
- }
- public static Complex64 MakeReal(double real) {
- return new Complex64(real, 0.0);
- }
- public static Complex64 Make(double real, double imag) {
- return new Complex64(real, imag);
- }
- public Complex64(double real)
- : this(real, 0.0) {
- }
- public Complex64(double real, double imag) {
- this.real = real;
- this.imag = imag;
- }
- public bool IsZero {
- get {
- return real == 0.0 && imag == 0.0;
- }
- }
- public double Real {
- get {
- return real;
- }
- }
- public double Imag {
- get {
- return imag;
- }
- }
- public Complex64 Conjugate() {
- return new Complex64(real, -imag);
- }
- public override string ToString() {
- if (real == 0.0) return imag.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + "j";
- else if (imag < 0.0) return string.Format(System.Globalization.CultureInfo.InvariantCulture.NumberFormat, "({0}{1}j)", real, imag);
- else return string.Format(System.Globalization.CultureInfo.InvariantCulture.NumberFormat, "({0}+{1}j)", real, imag);
- }
- public static implicit operator Complex64(bool b) {
- return b ? One : Zero;
- }
- public static implicit operator Complex64(int i) {
- return MakeReal(i);
- }
- [CLSCompliant(false)]
- public static implicit operator Complex64(uint i) {
- return MakeReal(i);
- }
- public static implicit operator Complex64(short i) {
- return MakeReal(i);
- }
-
- [CLSCompliant(false)]
- public static implicit operator Complex64(ushort i) {
- return MakeReal(i);
- }
- public static implicit operator Complex64(long l) {
- return MakeReal(l);
- }
- [CLSCompliant(false)]
- public static implicit operator Complex64(ulong i) {
- return MakeReal(i);
- }
- [CLSCompliant(false)]
- public static implicit operator Complex64(sbyte i) {
- return MakeReal(i);
- }
- public static implicit operator Complex64(byte i) {
- return MakeReal(i);
- }
- public static implicit operator Complex64(float f) {
- return MakeReal(f);
- }
- public static implicit operator Complex64(double d) {
- return MakeReal(d);
- }
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] // TODO: fix
- public static implicit operator Complex64(BigInteger i) {
- ContractUtils.RequiresNotNull(i, "i");
- // throws an overflow exception if we can't handle the value.
- return MakeReal((double)i);
- }
- #if FEATURE_NUMERICS
- public static implicit operator Complex64(BigInt i) {
- // throws an overflow exception if we can't handle the value.
- return MakeReal((double)i);
- }
- #endif
- public static bool operator ==(Complex64 x, Complex64 y) {
- return x.real == y.real && x.imag == y.imag;
- }
- public static bool operator !=(Complex64 x, Complex64 y) {
- return x.real != y.real || x.imag != y.imag;
- }
- public static Complex64 Add(Complex64 x, Complex64 y) {
- return x + y;
- }
- public static Complex64 operator +(Complex64 x, Complex64 y) {
- return new Complex64(x.real + y.real, x.imag + y.imag);
- }
- public static Complex64 Subtract(Complex64 x, Complex64 y) {
- return x - y;
- }
- public static Complex64 operator -(Complex64 x, Complex64 y) {
- return new Complex64(x.real - y.real, x.imag - y.imag);
- }
- public static Complex64 Multiply(Complex64 x, Complex64 y) {
- return x * y;
- }
- public static Complex64 operator *(Complex64 x, Complex64 y) {
- return new Complex64(x.real * y.real - x.imag * y.imag, x.real * y.imag + x.imag * y.real);
- }
- public static Complex64 Divide(Complex64 x, Complex64 y) {
- return x / y;
- }
- public static Complex64 operator /(Complex64 a, Complex64 b) {
- if (b.IsZero) {
- throw new DivideByZeroException("complex division by zero");
- }
- double real, imag, den, r;
- if (System.Math.Abs(b.real) >= System.Math.Abs(b.imag)) {
- r = b.imag / b.real;
- den = b.real + r * b.imag;
- real = (a.real + a.imag * r) / den;
- imag = (a.imag - a.real * r) / den;
- } else {
- r = b.real / b.imag;
- den = b.imag + r * b.real;
- real = (a.real * r + a.imag) / den;
- imag = (a.imag * r - a.real) / den;
- }
- return new Complex64(real, imag);
- }
- public static Complex64 Negate(Complex64 x) {
- return -x;
- }
- public static Complex64 operator -(Complex64 x) {
- return new Complex64(-x.real, -x.imag);
- }
- public static Complex64 Plus(Complex64 x) {
- return +x;
- }
- public static Complex64 operator +(Complex64 x) {
- return x;
- }
-
- [Obsolete("Deprecated - consider using MS.Scripting.Utils.MathUtils.Hypot")]
- public static double Hypot(double x, double y) {
- return MathUtils.Hypot(x, y);
- }
- public double Abs() {
- return MathUtils.Hypot(real, imag);
- }
- public Complex64 Power(Complex64 y) {
- double c = y.real;
- double d = y.imag;
- int power = (int)c;
- if (power == c && power >= 0 && d == .0) {
- Complex64 result = One;
- if (power == 0) return result;
- Complex64 factor = this;
- while (power != 0) {
- if ((power & 1) != 0) {
- result = result * factor;
- }
- factor = factor * factor;
- power >>= 1;
- }
- return result;
- } else if (IsZero) {
- return y.IsZero ? One : Zero;
- } else {
- double a = real;
- double b = imag;
- double powers = a * a + b * b;
- double arg = System.Math.Atan2(b, a);
- double mul = System.Math.Pow(powers, c / 2) * System.Math.Exp(-d * arg);
- double common = c * arg + .5 * d * System.Math.Log(powers);
- return new Complex64(mul * System.Math.Cos(common), mul * System.Math.Sin(common));
- }
- }
- public override int GetHashCode() {
- // The Object.GetHashCode function needs to be consistent with the Object.Equals function.
- // Languages that build on top of this may have a more flexible equality function and
- // so may not be able to use this hash function directly.
- // For example, Python allows that c=Complex64(1.5, 0), f = 1.5f, c==f.
- // so then the hash(f) == hash(c). Since the python (and other languages) can define an arbitrary
- // hash(float) function, the language may need to define a matching hash(complex) function for
- // the cases where the float and complex numbers overlap.
- return (int)real + (int)imag * 1000003;
- }
- public override bool Equals(object obj) {
- if (!(obj is Complex64)) return false;
- return this == ((Complex64)obj);
- }
- }
- }