Math.NET Numerics
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

137 lines
5.0 KiB

// (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>]
[<StructuralEquality(false); StructuralComparison(false)>]
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
[<OverloadID("Complex_Complex")>]
static member ( * ) (a,b) = Complex.mul a b
static member ( / ) (a,b) = Complex.div a b
static member ( ~- ) a = Complex.neg a
[<OverloadID("float_Complex")>]
static member ( * ) (a,b) = Complex.smul a b
[<OverloadID("Complex_float")>]
static member ( * ) (a,b) = Complex.muls a b
namespace Microsoft.FSharp.Core
type complex = Microsoft.FSharp.Math.Complex
module ComplexCommonExtensions =
let complex x y = Microsoft.FSharp.Math.Complex.mkRect (x,y)