From b4da72e6f594be878c41c85f6edac943869f6fae Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Tue, 4 Dec 2012 22:51:24 +0100 Subject: [PATCH] F#: single precision complex32 type, in addition to double precision complex --- src/FSharp/Complex.fs | 98 +++++++++++++++++++---- src/FSharp/Complex.fsi | 178 ++++++++++++++++++++++++++++++++++------- 2 files changed, 231 insertions(+), 45 deletions(-) diff --git a/src/FSharp/Complex.fs b/src/FSharp/Complex.fs index 53d69416..cfe96299 100644 --- a/src/FSharp/Complex.fs +++ b/src/FSharp/Complex.fs @@ -10,6 +10,7 @@ namespace MathNet.Numerics open System.Numerics type complex = Complex + type complex32 = Complex32 [] [] @@ -18,6 +19,7 @@ namespace MathNet.Numerics let mkRect(a,b) = new Complex(a,b) let mkPolar(a,b) = Complex.FromPolarCoordinates(a,b) let cis b = mkPolar(1.0,b) + let ofComplex32 (x:complex32) = new Complex(float x.Real, float x.Imaginary) let zero = Complex.Zero let one = Complex.One @@ -44,10 +46,10 @@ namespace MathNet.Numerics 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 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 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) @@ -59,28 +61,92 @@ namespace MathNet.Numerics 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 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 Complex32 = + + let mkRect(a,b) = new Complex32(a,b) + let mkPolar(a,b) = Complex32.FromPolarCoordinates(a,b) + let cis b = mkPolar(1.0f,b) + let ofComplex (x:complex) = new Complex32(float32 x.Real, float32 x.Imaginary) + + let zero = Complex32.Zero + let one = Complex32.One + let onei = Complex32.ImaginaryOne + let pi = mkRect (float32 Math.PI,0.0f) + + let realPart (c:complex32) = c.Real + let imagPart (c:complex32) = c.Imaginary + let magnitude (c:complex32) = c.Magnitude + let phase (c:complex32) = c.Phase + + let neg (a:complex32) = -a + let conjugate (c:complex32) = c.Conjugate() + + let add (a:complex32) (b:complex32) = a + b + let sub (a:complex32) (b:complex32) = a - b + let mul (a:complex32) (b:complex32) = a * b + let div (x:complex32) (y:complex32) = x / y + + let smul (a:float32) (b:complex32) = new Complex32(a * b.Real, a * b.Imaginary) + let muls (a:complex32) (b:float32) = new Complex32(a.Real * b, a.Imaginary * b) + + let exp (x:complex32) = Complex32.Exp(x) + let ln x = Complex32.Log(x) + let log10 x = Complex32.Log10(x) + let log b x = Complex32.Log(x,b) + let pow (power:complex32) x = Complex32.Pow(x,power) + let powf (power:float32) x = Complex32.Pow(x,power) + let sqr (x:complex32) = x.Square() + let sqrt (x:complex32) = x.SquareRoot() // numerically more stable than Complex.Sqrt + + let sin x = Complex32.Sin(x) + let cos x = Complex32.Cos(x) + let tan x = Complex32.Tan(x) + let asin x = Complex32.Asin(x) + let acos x = Complex32.Acos(x) + let atan x = Complex32.Atan(x) + let sinh x = Complex32.Sinh(x) + let cosh x = Complex32.Cosh(x) + let tanh x = Complex32.Tanh(x) + + // no complex32 implementations available yet, fix once available + let sec (x:complex32) = ofComplex <| Trig.Secant(x.ToComplex()) + let csc (x:complex32) = ofComplex <| Trig.Cosecant(x.ToComplex()) + let cot (x:complex32) = ofComplex <| Trig.Cotangent(x.ToComplex()) + let asec (x:complex32) = ofComplex <| Trig.InverseSecant(x.ToComplex()) + let acsc (x:complex32) = ofComplex <| Trig.InverseCosecant(x.ToComplex()) + let acot (x:complex32) = ofComplex <| Trig.InverseCotangent(x.ToComplex()) + let sech (x:complex32) = ofComplex <| Trig.HyperbolicSecant(x.ToComplex()) + let csch (x:complex32) = ofComplex <| Trig.HyperbolicCosecant(x.ToComplex()) + let coth (x:complex32) = ofComplex <| Trig.HyperbolicCotangent(x.ToComplex()) [] module ComplexExtensions = let complex x y = Complex.mkRect (x,y) + let complex32 x y = Complex32.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) \ No newline at end of file + static member CreatePolar(a,b) = Complex.mkPolar (a,b) + + type Complex32 with + member x.r = x.Real + member x.i = x.Imaginary + + static member Create(a,b) = Complex32.mkRect (a,b) + static member CreatePolar(a,b) = Complex32.mkPolar (a,b) diff --git a/src/FSharp/Complex.fsi b/src/FSharp/Complex.fsi index 4df15c17..605cb4cb 100644 --- a/src/FSharp/Complex.fsi +++ b/src/FSharp/Complex.fsi @@ -9,6 +9,7 @@ namespace MathNet.Numerics /// The type of complex numbers type complex = Complex + type complex32 = Complex32 [] [] @@ -28,7 +29,7 @@ namespace MathNet.Numerics /// The complex number 0+1i val onei : complex /// pi - val pi : Complex + val pi : complex /// The real part of a complex number val realPart : complex -> float @@ -59,65 +60,171 @@ namespace MathNet.Numerics val muls : complex -> float -> complex /// exp(x) = e^x - val exp : Complex -> Complex + val exp : complex -> complex /// ln(x) is natural log (base e) - val ln : Complex -> Complex + val ln : complex -> complex /// log10(x) is common log (base 10) - val log10 : Complex -> Complex + val log10 : complex -> complex /// log(base,x) is log with custom base - val log : float -> Complex -> Complex + val log : float -> complex -> complex /// pow(power,x) is the complex power - val pow : Complex -> Complex -> Complex + val pow : complex -> complex -> complex /// pow(power,x) is the float power - val powf : float -> Complex -> Complex + val powf : float -> complex -> complex /// sqr(x) is the square (power 2) - val sqr : Complex -> Complex + val sqr : complex -> complex /// sqrt(x) and 0 <= phase(x) < pi - val sqrt : Complex -> Complex + val sqrt : complex -> complex /// Sine - val sin : Complex -> Complex + val sin : complex -> complex /// Cosine - val cos : Complex -> Complex + val cos : complex -> complex /// Tagent - val tan : Complex -> Complex + val tan : complex -> complex /// Arc Sine - val asin : Complex -> Complex + val asin : complex -> complex /// Arc Cosine - val acos : Complex -> Complex + val acos : complex -> complex /// Arc Tagent - val atan : Complex -> Complex + val atan : complex -> complex /// Hyperbolic Sine - val sinh : Complex -> Complex + val sinh : complex -> complex /// Hyperbolic Cosine - val cosh : Complex -> Complex + val cosh : complex -> complex /// Hyperbolic Tagent - val tanh : Complex -> Complex + val tanh : complex -> complex /// Secant - val sec : Complex -> Complex + val sec : complex -> complex /// Cosecant - val csc : Complex -> Complex + val csc : complex -> complex /// Cotangent - val cot : Complex -> Complex + val cot : complex -> complex /// Arc Secant - val asec : Complex -> Complex + val asec : complex -> complex /// Arc Cosecant - val acsc : Complex -> Complex + val acsc : complex -> complex /// Arc Cotangent - val acot : Complex -> Complex + val acot : complex -> complex /// Hyperbolic Secant - val sech : Complex -> Complex + val sech : complex -> complex /// Hyperbolic Cosecant - val csch : Complex -> Complex + val csch : complex -> complex /// Hyperbolic Cotangent - val coth : Complex -> Complex + val coth : complex -> complex + + [] + [] + module Complex32 = + + /// Create a complex number using real and imaginary parts + val mkRect : float32 * float32 -> complex32 + /// Create a complex number using magnitude/phase polar coordinates + val mkPolar : float32 * float32 -> complex32 + /// A complex of magnitude 1 and the given phase and , i.e. cis x = mkPolar 1.0 x + val cis : float32 -> complex32 + + /// The complex number 0+0i + val zero : complex32 + /// The complex number 1+0i + val one : complex32 + /// The complex number 0+1i + val onei : complex32 + /// pi + val pi : complex32 + + /// The real part of a complex number + val realPart : complex32 -> float32 + /// The imaginary part of a complex number + val imagPart : complex32 -> float32 + /// The polar-coordinate magnitude of a complex number + val magnitude : complex32 -> float32 + /// The polar-coordinate phase of a complex number + val phase : complex32 -> float32 + + /// Unary negation of a complex number + val neg : complex32 -> complex32 + /// The conjugate of a complex number, i.e. x-yi + val conjugate : complex32 -> complex32 + + /// Add two complex numbers + val add : complex32 -> complex32 -> complex32 + /// Subtract one complex number from another + val sub : complex32 -> complex32 -> complex32 + /// Multiply two complex numbers + val mul : complex32 -> complex32 -> complex32 + /// Complex division of two complex numbers + val div : complex32 -> complex32 -> complex32 + + /// Multiply a scalar by a complex number + val smul : float32 -> complex32 -> complex32 + /// Multiply a complex number by a scalar + val muls : complex32 -> float32 -> complex32 + + /// exp(x) = e^x + val exp : complex32 -> complex32 + /// ln(x) is natural log (base e) + val ln : complex32 -> complex32 + /// log10(x) is common log (base 10) + val log10 : complex32 -> complex32 + /// log(base,x) is log with custom base + val log : float32 -> complex32 -> complex32 + /// pow(power,x) is the complex power + val pow : complex32 -> complex32 -> complex32 + /// pow(power,x) is the float power + val powf : float32 -> complex32 -> complex32 + /// sqr(x) is the square (power 2) + val sqr : complex32 -> complex32 + /// sqrt(x) and 0 <= phase(x) < pi + val sqrt : complex32 -> complex32 + + /// Sine + val sin : complex32 -> complex32 + /// Cosine + val cos : complex32 -> complex32 + /// Tagent + val tan : complex32 -> complex32 + /// Arc Sine + val asin : complex32 -> complex32 + /// Arc Cosine + val acos : complex32 -> complex32 + /// Arc Tagent + val atan : complex32 -> complex32 + /// Hyperbolic Sine + val sinh : complex32 -> complex32 + /// Hyperbolic Cosine + val cosh : complex32 -> complex32 + /// Hyperbolic Tagent + val tanh : complex32 -> complex32 + + /// Secant + val sec : complex32 -> complex32 + /// Cosecant + val csc : complex32 -> complex32 + /// Cotangent + val cot : complex32 -> complex32 + /// Arc Secant + val asec : complex32 -> complex32 + /// Arc Cosecant + val acsc : complex32 -> complex32 + /// Arc Cotangent + val acot : complex32 -> complex32 + /// Hyperbolic Secant + val sech : complex32 -> complex32 + /// Hyperbolic Cosecant + val csch : complex32 -> complex32 + /// Hyperbolic Cotangent + val coth : complex32 -> complex32 [] module ComplexExtensions = - /// Constructs a complex number from both the real and imaginary part. + /// Constructs a double precision complex number from both the real and imaginary part. val complex : float -> float -> complex + + /// Constructs a single precision complex number from both the real and imaginary part. + val complex32 : float32 -> float32 -> complex32 /// The type of complex numbers stored as pairs of 64-bit floating point numbers in rectangular coordinates type Complex with @@ -130,4 +237,17 @@ namespace MathNet.Numerics /// 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 + member i: float + + /// The type of complex numbers stored as pairs of 32-bit floating point numbers in rectangular coordinates + type Complex32 with + + /// Create a complex number x+ij using rectangular coordinates + static member Create : float32 * float32 -> Complex32 + /// Create a complex number using magnitude/phase polar coordinates + static member CreatePolar : float32 * float32 -> Complex32 + + /// The real part of a complex number + member r: float32 + /// The imaginary part of a complex number + member i: float32