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
|
// (c) Microsoft Corporation 2005-2009.
#nowarn "52" // defensive copy of structs warning
namespace Microsoft.FSharp.Math
open Microsoft.FSharp.Math
open System
open System.Globalization
[<Struct>]
[<CustomEquality; CustomComparison>]
type Complex(real: float, imaginary: float) =
//new() = new Complex(0.0,0.0)
member x.r = real
member x.i = imaginary
override x.ToString() = x.ToString("g")
member x.ToString(fmt) = x.ToString(fmt,CultureInfo.InvariantCulture)
member x.ToString(fmt,fmtprovider:IFormatProvider) =
x.r.ToString(fmt,fmtprovider)+"r"+(if x.i < 0.0 then "-" else "+")+(System.Math.Abs x.i).ToString(fmt,fmtprovider)+"i"
interface IComparable with
member x.CompareTo(obj) =
match obj with
| :? Complex as y ->
let c = compare x.r y.r
if c <> 0 then c else compare x.i y.i
| _ -> invalidArg "obj" "not a Complex number"
override x.Equals(obj) =
match obj with
| :? Complex as y -> x.r = y.r && x.i = y.i
| _ -> false
override x.GetHashCode() =
(hash x.r >>> 5) ^^^ (hash x.r <<< 3) ^^^ (((hash x.i >>> 4) ^^^ (hash x.i <<< 4)) + 0x9e3779b9)
type complex = Complex
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Complex =
let mkRect(a,b) = new Complex(a,b)
let conjugate (c:complex) = mkRect (c.r, -c.i)
let mkPolar(a,b) = mkRect (a * Math.Cos(b), a * Math.Sin(b))
let cis b = mkPolar(1.0,b)
let zero = mkRect(0.,0.)
let one = mkRect(1.,0.)
let onei = mkRect(0.,1.)
let magnitude (c:complex) = sqrt(c.r*c.r + c.i*c.i)
let phase (c:complex) = Math.Atan2(c.i,c.r)
let realPart (c:complex) = c.r
let imagPart (c:complex) = c.i
let abs (a:complex) = sqrt (a.r**2.0 + a.i**2.0)
let add (a:complex) (b:complex) = mkRect(a.r + b.r, a.i+b.i)
let sub (a:complex) (b:complex) = mkRect(a.r - b.r, a.i-b.i)
let mul (a:complex) (b:complex) = mkRect(a.r * b.r - a.i * b.i, a.i*b.r + b.i*a.r)
let div (x:complex) (y:complex) =
let a = x.r in let b = x.i in
let c = y.r in let d = y.i in
//(a+ib)/(c+id)=(ac+bd+i(bc-ad))/(c2+d2)
let q = c*c + d*d in
mkRect((a*c+b*d)/q, (b*c - a*d)/q)
let neg (a:complex) = mkRect(-a.r,-a.i)
let smul (a:float)(b:complex) = mkRect(a * b.r, a*b.i)
let muls (a:complex) (b:float) = mkRect(a.r *b, a.i*b)
let fmt_of_string numstyle fmtprovider (s:string) =
mkRect (System.Double.Parse(s,numstyle,fmtprovider),0.0)
let of_string s = fmt_of_string NumberStyles.Any CultureInfo.InvariantCulture s
// ik.(r + i.th) = -k.th + i.k.r
let iscale k (x:complex) = mkRect (-k * x.i , k * x.r)
// LogN : 'a * 'a -> 'a
// Asin : 'a -> 'a
// Acos : 'a -> 'a
// Atan : 'a -> 'a
// Atan2 : 'a * 'a -> 'a
// Sinh : 'a -> 'a
// Cosh : 'a -> 'a
// Tanh : 'a -> 'a
let pi = mkRect (Math.PI,0.0)
// exp(r+it) = exp(r).(cos(t)+i.sin(t)) - De Moivre Theorem
let exp (x:complex) = smul (exp(x.r)) (mkRect(cos(x.i), sin(x.i)))
// x = mag.e^(i.th) = e^ln(mag).e^(i.th) = e^(ln(mag) + i.th)
let log x = mkRect (log(magnitude(x)),phase(x))
let sqrt x = mkPolar (sqrt(magnitude x),phase x / 2.0)
// cos(x) = (exp(i.x) + exp(-i.x))/2
let cos x = smul 0.5 (add (exp(iscale 1.0 x)) (exp(iscale -1.0 x)))
// sin(x) = (exp(i.x) - exp(-i.x))/2 . (-i)
let sin x = smul 0.5 (sub (exp(iscale 1.0 x)) (exp(iscale -1.0 x))) |> iscale (-1.0)
// tan(x) = (exp(i.x) - exp(-i.x)) . (-i) / (exp(i.x) + exp(-i.x))
// = (exp(2i.x) - 1.0) . (-i) / (exp(2i.x) + 1.0)
let tan x = let exp2ix = exp(iscale 2.0 x) in
(div (sub exp2ix one) (add exp2ix one)) |> iscale -1.0
type Complex with
static member Create(a,b) = Complex.mkRect (a,b)
static member CreatePolar(a,b) = Complex.mkPolar (a,b)
member x.Magnitude = Complex.magnitude x
member x.Phase = Complex.phase x
member x.RealPart = x.r
member x.ImaginaryPart = x.i
member x.Conjugate = Complex.conjugate x
static member Sin(x) = Complex.sin(x)
static member Cos(x) = Complex.cos(x)
static member Abs(x) = Complex.abs(x)
static member Tan(x) = Complex.tan(x)
static member Log(x) = Complex.log(x)
static member Exp(x) = Complex.exp(x)
static member Sqrt(x) = Complex.sqrt(x)
static member Zero = Complex.zero
static member One = Complex.one
static member OneI = Complex.onei
static member ( + ) (a,b) = Complex.add a b
static member ( - ) (a,b) = Complex.sub a b
static member ( * ) (a,b) = Complex.mul a b
static member ( / ) (a,b) = Complex.div a b
static member ( ~- ) a = Complex.neg a
static member ( * ) (a,b) = Complex.smul a b
static member ( * ) (a,b) = Complex.muls a b
module ComplexTopLevelOperators =
let complex x y = Complex.mkRect (x,y)
|