PageRenderTime 51ms CodeModel.GetById 27ms RepoModel.GetById 0ms 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
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  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. using System;
  16. using Microsoft.Scripting.Utils;
  17. #if !CLR2
  18. using BigInt = System.Numerics.BigInteger;
  19. #endif
  20. namespace Microsoft.Scripting.Math {
  21. /// <summary>
  22. /// Implementation of the complex number data type.
  23. /// </summary>
  24. [Serializable]
  25. public struct Complex64 {
  26. public static readonly Complex64 Zero = new Complex64(0.0, 0.0);
  27. public static readonly Complex64 One = new Complex64(1.0, 0.0);
  28. public static readonly Complex64 ImaginaryOne = new Complex64(0.0, 1.0);
  29. private readonly double real, imag;
  30. public static Complex64 MakeImaginary(double imag) {
  31. return new Complex64(0.0, imag);
  32. }
  33. public static Complex64 MakeReal(double real) {
  34. return new Complex64(real, 0.0);
  35. }
  36. public static Complex64 Make(double real, double imag) {
  37. return new Complex64(real, imag);
  38. }
  39. public Complex64(double real)
  40. : this(real, 0.0) {
  41. }
  42. public Complex64(double real, double imag) {
  43. this.real = real;
  44. this.imag = imag;
  45. }
  46. public bool IsZero {
  47. get {
  48. return real == 0.0 && imag == 0.0;
  49. }
  50. }
  51. public double Real {
  52. get {
  53. return real;
  54. }
  55. }
  56. public double Imag {
  57. get {
  58. return imag;
  59. }
  60. }
  61. public Complex64 Conjugate() {
  62. return new Complex64(real, -imag);
  63. }
  64. public override string ToString() {
  65. if (real == 0.0) return imag.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + "j";
  66. else if (imag < 0.0) return string.Format(System.Globalization.CultureInfo.InvariantCulture.NumberFormat, "({0}{1}j)", real, imag);
  67. else return string.Format(System.Globalization.CultureInfo.InvariantCulture.NumberFormat, "({0}+{1}j)", real, imag);
  68. }
  69. public static implicit operator Complex64(bool b) {
  70. return b ? One : Zero;
  71. }
  72. public static implicit operator Complex64(int i) {
  73. return MakeReal(i);
  74. }
  75. [CLSCompliant(false)]
  76. public static implicit operator Complex64(uint i) {
  77. return MakeReal(i);
  78. }
  79. public static implicit operator Complex64(short i) {
  80. return MakeReal(i);
  81. }
  82. [CLSCompliant(false)]
  83. public static implicit operator Complex64(ushort i) {
  84. return MakeReal(i);
  85. }
  86. public static implicit operator Complex64(long l) {
  87. return MakeReal(l);
  88. }
  89. [CLSCompliant(false)]
  90. public static implicit operator Complex64(ulong i) {
  91. return MakeReal(i);
  92. }
  93. [CLSCompliant(false)]
  94. public static implicit operator Complex64(sbyte i) {
  95. return MakeReal(i);
  96. }
  97. public static implicit operator Complex64(byte i) {
  98. return MakeReal(i);
  99. }
  100. public static implicit operator Complex64(float f) {
  101. return MakeReal(f);
  102. }
  103. public static implicit operator Complex64(double d) {
  104. return MakeReal(d);
  105. }
  106. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] // TODO: fix
  107. public static implicit operator Complex64(BigInteger i) {
  108. ContractUtils.RequiresNotNull(i, "i");
  109. // throws an overflow exception if we can't handle the value.
  110. return MakeReal((double)i);
  111. }
  112. #if !CLR2
  113. public static implicit operator Complex64(BigInt i) {
  114. // throws an overflow exception if we can't handle the value.
  115. return MakeReal((double)i);
  116. }
  117. #endif
  118. public static bool operator ==(Complex64 x, Complex64 y) {
  119. return x.real == y.real && x.imag == y.imag;
  120. }
  121. public static bool operator !=(Complex64 x, Complex64 y) {
  122. return x.real != y.real || x.imag != y.imag;
  123. }
  124. public static Complex64 Add(Complex64 x, Complex64 y) {
  125. return x + y;
  126. }
  127. public static Complex64 operator +(Complex64 x, Complex64 y) {
  128. return new Complex64(x.real + y.real, x.imag + y.imag);
  129. }
  130. public static Complex64 Subtract(Complex64 x, Complex64 y) {
  131. return x - y;
  132. }
  133. public static Complex64 operator -(Complex64 x, Complex64 y) {
  134. return new Complex64(x.real - y.real, x.imag - y.imag);
  135. }
  136. public static Complex64 Multiply(Complex64 x, Complex64 y) {
  137. return x * y;
  138. }
  139. public static Complex64 operator *(Complex64 x, Complex64 y) {
  140. return new Complex64(x.real * y.real - x.imag * y.imag, x.real * y.imag + x.imag * y.real);
  141. }
  142. public static Complex64 Divide(Complex64 x, Complex64 y) {
  143. return x / y;
  144. }
  145. public static Complex64 operator /(Complex64 a, Complex64 b) {
  146. if (b.IsZero) {
  147. throw new DivideByZeroException("complex division by zero");
  148. }
  149. double real, imag, den, r;
  150. if (System.Math.Abs(b.real) >= System.Math.Abs(b.imag)) {
  151. r = b.imag / b.real;
  152. den = b.real + r * b.imag;
  153. real = (a.real + a.imag * r) / den;
  154. imag = (a.imag - a.real * r) / den;
  155. } else {
  156. r = b.real / b.imag;
  157. den = b.imag + r * b.real;
  158. real = (a.real * r + a.imag) / den;
  159. imag = (a.imag * r - a.real) / den;
  160. }
  161. return new Complex64(real, imag);
  162. }
  163. public static Complex64 Negate(Complex64 x) {
  164. return -x;
  165. }
  166. public static Complex64 operator -(Complex64 x) {
  167. return new Complex64(-x.real, -x.imag);
  168. }
  169. public static Complex64 Plus(Complex64 x) {
  170. return +x;
  171. }
  172. public static Complex64 operator +(Complex64 x) {
  173. return x;
  174. }
  175. [Obsolete("Deprecated - consider using MS.Scripting.Utils.MathUtils.Hypot")]
  176. public static double Hypot(double x, double y) {
  177. return MathUtils.Hypot(x, y);
  178. }
  179. public double Abs() {
  180. return MathUtils.Hypot(real, imag);
  181. }
  182. public Complex64 Power(Complex64 y) {
  183. double c = y.real;
  184. double d = y.imag;
  185. int power = (int)c;
  186. if (power == c && power >= 0 && d == .0) {
  187. Complex64 result = One;
  188. if (power == 0) return result;
  189. Complex64 factor = this;
  190. while (power != 0) {
  191. if ((power & 1) != 0) {
  192. result = result * factor;
  193. }
  194. factor = factor * factor;
  195. power >>= 1;
  196. }
  197. return result;
  198. } else if (IsZero) {
  199. return y.IsZero ? One : Zero;
  200. } else {
  201. double a = real;
  202. double b = imag;
  203. double powers = a * a + b * b;
  204. double arg = System.Math.Atan2(b, a);
  205. double mul = System.Math.Pow(powers, c / 2) * System.Math.Exp(-d * arg);
  206. double common = c * arg + .5 * d * System.Math.Log(powers);
  207. return new Complex64(mul * System.Math.Cos(common), mul * System.Math.Sin(common));
  208. }
  209. }
  210. public override int GetHashCode() {
  211. // The Object.GetHashCode function needs to be consistent with the Object.Equals function.
  212. // Languages that build on top of this may have a more flexible equality function and
  213. // so may not be able to use this hash function directly.
  214. // For example, Python allows that c=Complex64(1.5, 0), f = 1.5f, c==f.
  215. // so then the hash(f) == hash(c). Since the python (and other languages) can define an arbitrary
  216. // hash(float) function, the language may need to define a matching hash(complex) function for
  217. // the cases where the float and complex numbers overlap.
  218. return (int)real + (int)imag * 1000003;
  219. }
  220. public override bool Equals(object obj) {
  221. if (!(obj is Complex64)) return false;
  222. return this == ((Complex64)obj);
  223. }
  224. }
  225. }