Browse Source

F#: Complex: cleanup, no need to reimplement everything, module more thorough

v2
Christoph Ruegg 14 years ago
parent
commit
618a4b6498
  1. 178
      src/FSharp/Complex.fs
  2. 216
      src/FSharp/Complex.fsi

178
src/FSharp/Complex.fs

@ -1,10 +1,7 @@
// First version copied from the F# Power Pack
// https://raw.github.com/fsharp/powerpack/master/src/FSharp.PowerPack/math/complex.fs
// (c) Microsoft Corporation 2005-2009.
#nowarn "52" // defensive copy of structs warning
namespace MathNet.Numerics
open Microsoft.FSharp.Math
@ -12,125 +9,78 @@ namespace MathNet.Numerics
open System.Globalization
open System.Numerics
(*
[<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
[<AutoOpen>]
module private ComplexExtensionsBasic =
type Complex with
member x.r = x.Real
member x.i = x.Imaginary
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
[<RequireQualifiedAccess>]
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
let mkRect(a,b) = new Complex(a,b)
let mkPolar(a,b) = Complex.FromPolarCoordinates(a,b)
let cis b = mkPolar(1.0,b)
let zero = Complex.Zero
let one = Complex.One
let onei = Complex.ImaginaryOne
let pi = mkRect (Math.PI,0.0)
let realPart (c:complex) = c.Real
let imagPart (c:complex) = c.Imaginary
let magnitude (c:complex) = c.Magnitude
let phase (c:complex) = c.Phase
let neg (a:complex) = -a
let conjugate (c:complex) = c.Conjugate()
let add (a:complex) (b:complex) = a + b
let sub (a:complex) (b:complex) = a - b
let mul (a:complex) (b:complex) = a * b
let div (x:complex) (y:complex) = x / y
let smul (a:float) (b:complex) = new Complex(a * b.Real, a * b.Imaginary)
let muls (a:complex) (b:float) = new Complex(a.Real * b, a.Imaginary * b)
let exp (x:complex) = Complex.Exp(x)
let ln x = Complex.Log(x)
let log10 x = Complex.Log10(x)
let log b x = Complex.Log(x,b)
let pow (power:Complex) x = Complex.Pow(x,power)
let powf (power:float) x = Complex.Pow(x,power)
let sqr (x:Complex) = x.Square()
let sqrt (x:Complex) = x.SquareRoot() // numerically more stable than Complex.Sqrt
let sin x = Complex.Sin(x)
let cos x = Complex.Cos(x)
let tan x = Complex.Tan(x)
let asin x = Complex.Asin(x)
let acos x = Complex.Acos(x)
let atan x = Complex.Atan(x)
let sinh x = Complex.Sinh(x)
let cosh x = Complex.Cosh(x)
let tanh x = Complex.Tanh(x)
let sec (x:Complex) = Trig.Secant(x)
let csc (x:Complex) = Trig.Cosecant(x)
let cot (x:Complex) = Trig.Cotangent(x)
let asec (x:Complex) = Trig.InverseSecant(x)
let acsc (x:Complex) = Trig.InverseCosecant(x)
let acot (x:Complex) = Trig.InverseCotangent(x)
let sech (x:Complex) = Trig.HyperbolicSecant(x)
let csch (x:Complex) = Trig.HyperbolicCosecant(x)
let coth (x:Complex) = Trig.HyperbolicCotangent(x)
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
[<AutoOpen>]
module ComplexExtensions =
let complex x y = Complex.mkRect (x,y)
type Complex with
member x.r = x.Real
member x.i = x.Imaginary
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
module ComplexTopLevelOperators =
let complex x y = Complex.mkRect (x,y)
static member CreatePolar(a,b) = Complex.mkPolar (a,b)

216
src/FSharp/Complex.fsi

@ -1,6 +1,5 @@
// First version copied from the F# Power Pack
// https://raw.github.com/fsharp/powerpack/master/src/FSharp.PowerPack/math/complex.fsi
// (c) Microsoft Corporation 2005-2009.
namespace MathNet.Numerics
@ -8,134 +7,127 @@ namespace MathNet.Numerics
open System
open System.Numerics
[<AutoOpen>]
module ComplexExtensions =
/// The type of complex numbers stored as pairs of 64-bit floating point numbers in rectangular coordinates
type Complex with
/// The real part of a complex number
member r: float
/// The imaginary part of a complex number
member i: float
/// The polar-coordinate magnitude of a complex number
member Magnitude: float
/// The polar-coordinate phase of a complex number
member Phase: float
/// The real part of a complex number
member RealPart: float
/// The imaginary part of a complex number
member ImaginaryPart: float
/// The conjugate of a complex number, i.e. x-yi
member Conjugate: Complex
/// Create a complex number x+ij using rectangular coordinates
static member Create : float * float -> Complex
/// Create a complex number using magnitude/phase polar coordinates
static member CreatePolar : float * float -> Complex
/// The complex number 0+0i
static member Zero : Complex
/// The complex number 1+0i
static member One : Complex
/// The complex number 0+1i
static member OneI : Complex
(*
/// Add two complex numbers
static member ( + ) : Complex * Complex -> Complex
/// Subtract one complex number from another
static member ( - ) : Complex * Complex -> Complex
/// Multiply two complex numbers
static member ( * ) : Complex * Complex -> Complex
/// Complex division of two complex numbers
static member ( / ) : Complex * Complex -> Complex
/// Unary negation of a complex number
static member ( ~- ) : Complex -> Complex
/// Multiply a scalar by a complex number
static member ( * ) : float * Complex -> Complex
/// Multiply a complex number by a scalar
static member ( * ) : Complex * float -> Complex
*)
static member Sin : Complex -> Complex
static member Cos : Complex -> Complex
/// Computes the absolute value of a complex number: e.g. Abs x+iy = sqrt(x**2.0 + y**2.0.)
/// Note: Complex.Abs(z) is the same as z.Magnitude
static member Abs : Complex -> float
static member Tan : Complex -> Complex
static member Log : Complex -> Complex
static member Exp : Complex -> Complex
static member Sqrt : Complex -> Complex
(*
override ToString : unit -> string
override Equals : obj -> bool
interface System.IComparable
member ToString : format:string -> string
member ToString : format:string * provider:System.IFormatProvider -> string
*)
/// The type of complex numbers
type complex = Complex
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
[<RequireQualifiedAccess>]
module Complex =
val mkRect: float * float -> complex
/// The polar-coordinate magnitude of a complex number
val magnitude: complex -> float
/// The polar-coordinate phase of a complex number
val phase : complex -> float
/// The real part of a complex number
val realPart : complex -> float
/// The imaginary part of a complex number
val imagPart : complex -> float
/// Create a complex number using magnitude/phase polar coordinates
/// Create a complex number using real and imaginary parts
val mkRect : float * float -> complex
/// Create a complex number using magnitude/phase polar coordinates
val mkPolar : float * float -> complex
/// A complex of magnitude 1 and the given phase and , i.e. cis x = mkPolar 1.0 x
val cis : float -> complex
/// The conjugate of a complex number, i.e. x-yi
val cis : float -> complex
/// The complex number 0+0i
val zero : complex
/// The complex number 1+0i
val one : complex
/// The complex number 0+1i
val onei : complex
/// pi
val pi : Complex
/// The real part of a complex number
val realPart : complex -> float
/// The imaginary part of a complex number
val imagPart : complex -> float
/// The polar-coordinate magnitude of a complex number
val magnitude : complex -> float
/// The polar-coordinate phase of a complex number
val phase : complex -> float
/// Unary negation of a complex number
val neg : complex -> complex
/// The conjugate of a complex number, i.e. x-yi
val conjugate : complex -> complex
/// The complex number 0+0i
val zero : complex
/// The complex number 1+0i
val one : complex
/// The complex number 0+1i
val onei : complex
/// Add two complex numbers
val add : complex -> complex -> complex
/// Subtract one complex number from another
val sub : complex -> complex -> complex
/// Multiply two complex numbers
val mul : complex -> complex -> complex
/// Complex division of two complex numbers
val div : complex -> complex -> complex
/// Unary negation of a complex number
val neg : complex -> complex
/// Multiply a scalar by a complex number
val smul : float -> complex -> complex
/// Multiply a complex number by a scalar
val muls : complex -> float -> complex
/// pi
val pi : Complex
/// exp(x) = e^x
/// Add two complex numbers
val add : complex -> complex -> complex
/// Subtract one complex number from another
val sub : complex -> complex -> complex
/// Multiply two complex numbers
val mul : complex -> complex -> complex
/// Complex division of two complex numbers
val div : complex -> complex -> complex
/// Multiply a scalar by a complex number
val smul : float -> complex -> complex
/// Multiply a complex number by a scalar
val muls : complex -> float -> complex
/// exp(x) = e^x
val exp : Complex -> Complex
/// log(x) is natural log (base e)
val log : Complex -> Complex
/// sqrt(x) and 0 <= phase(x) < pi
/// ln(x) is natural log (base e)
val ln : Complex -> Complex
/// log10(x) is common log (base 10)
val log10 : Complex -> Complex
/// log(base,x) is log with custom base
val log : float -> Complex -> Complex
/// pow(power,x) is the complex power
val pow : Complex -> Complex -> Complex
/// pow(power,x) is the float power
val powf : float -> Complex -> Complex
/// sqr(x) is the square (power 2)
val sqr : Complex -> Complex
/// sqrt(x) and 0 <= phase(x) < pi
val sqrt : Complex -> Complex
/// Sine
/// Sine
val sin : Complex -> Complex
/// Cosine
/// Cosine
val cos : Complex -> Complex
/// Tagent
/// Tagent
val tan : Complex -> Complex
/// Arc Sine
val asin : Complex -> Complex
/// Arc Cosine
val acos : Complex -> Complex
/// Arc Tagent
val atan : Complex -> Complex
/// Hyperbolic Sine
val sinh : Complex -> Complex
/// Hyperbolic Cosine
val cosh : Complex -> Complex
/// Hyperbolic Tagent
val tanh : Complex -> Complex
/// Secant
val sec : Complex -> Complex
/// Cosecant
val csc : Complex -> Complex
/// Cotangent
val cot : Complex -> Complex
/// Arc Secant
val asec : Complex -> Complex
/// Arc Cosecant
val acsc : Complex -> Complex
/// Arc Cotangent
val acot : Complex -> Complex
/// Hyperbolic Secant
val sech : Complex -> Complex
/// Hyperbolic Cosecant
val csch : Complex -> Complex
/// Hyperbolic Cotangent
val coth : Complex -> Complex
[<AutoOpen>]
module ComplexTopLevelOperators =
module ComplexExtensions =
/// Constructs a complex number from both the real and imaginary part.
val complex : float -> float -> complex
/// The type of complex numbers stored as pairs of 64-bit floating point numbers in rectangular coordinates
type Complex with
/// Create a complex number x+ij using rectangular coordinates
static member Create : float * float -> Complex
/// Create a complex number using magnitude/phase polar coordinates
static member CreatePolar : float * float -> Complex
/// The real part of a complex number
member r: float
/// The imaginary part of a complex number
member i: float
Loading…
Cancel
Save