diff --git a/src/FSharp/Complex.fs b/src/FSharp/Complex.fs index 3a3c91af..53d69416 100644 --- a/src/FSharp/Complex.fs +++ b/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 - (* - [] - [] - 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 - [] - module private ComplexExtensionsBasic = - type Complex with - member x.r = x.Real - member x.i = x.Imaginary - [] + [] 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 [] 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) \ No newline at end of file diff --git a/src/FSharp/Complex.fsi b/src/FSharp/Complex.fsi index 29308e16..4df15c17 100644 --- a/src/FSharp/Complex.fsi +++ b/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 - [] - 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 - [] [] 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 [] - 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 \ No newline at end of file