Skip to content

Commit

Permalink
More convenient interop with primitive number types
Browse files Browse the repository at this point in the history
  • Loading branch information
cdrnet committed Dec 30, 2018
1 parent 1b341e9 commit 15b800a
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 21 deletions.
4 changes: 2 additions & 2 deletions src/Symbolics/Approximate.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ open Operators
module Approximate =

[<CompiledName("Real")>]
let real x = Approximation.Real(x)
let real x = Approximation.fromReal x

[<CompiledName("Complex")>]
let complex r i = Approximation.Complex (complex r i)
let complex r i = Approximation.fromComplex (complex r i)

[<CompiledName("ApproximateSubstitute")>]
let rec approximateSubstitute (symbols:IDictionary<string, Approximation>) x =
Expand Down
13 changes: 13 additions & 0 deletions src/Symbolics/Approximation.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,28 @@
open System
open MathNet.Numerics

[<RequireQualifiedAccess>]
module internal Primitive =
let inline complex (x:complex32) = complex (float x.Real) (float x.Imaginary)


// this could be extended to arbitrary/custom precision approximations in the future
type Approximation =
| Real of float
| Complex of complex

// Simpler usage in C#
static member op_Implicit (x:float) = Real x
static member op_Implicit (x:float32) = Real (float x)
static member op_Implicit (x:complex) = Complex x
static member op_Implicit (x:complex32) = Complex (Primitive.complex x)

member x.RealValue =
match x with
| Real x -> x
| Complex x when x.IsReal() -> x.Real
| _ -> failwith "Value not convertible to a real number."

member x.ComplexValue =
match x with
| Real x -> complex x 0.0
Expand All @@ -27,6 +36,10 @@ type Approximation =
module Approximation =

let fromRational (x:BigRational) = Real (float x)
let fromReal (x:float) = Real x
let fromReal32 (x:float32) = Real (float x)
let fromComplex (x:complex) = Complex x
let fromComplex32 (x:complex32) = Complex (Primitive.complex x)

let negate = function
| Real a -> Real (-a)
Expand Down
2 changes: 2 additions & 0 deletions src/Symbolics/Evaluate.fs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ type FloatingPoint =

// Simpler usage in C#
static member op_Implicit (x:float) = Real x
static member op_Implicit (x:float32) = Real (float x)
static member op_Implicit (x:complex) = Complex x
static member op_Implicit (x:complex32) = Complex (Primitive.complex x)
static member op_Implicit (x:Vector<float>) = RealVector x
static member op_Implicit (x:Vector<complex>) = ComplexVector x
static member op_Implicit (x:Matrix<float>) = RealMatrix x
Expand Down
61 changes: 49 additions & 12 deletions src/Symbolics/Expression.fs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ module Values =
| Value.NegativeInfinity -> NegativeInfinity
| Value.Undefined -> Undefined

let real (x:float) = Value.real x |> unpack
let complex (x:complex) = Value.complex x |> unpack
let real (x:float) = Value.fromReal x |> unpack
let real32 (x:float32) = Value.fromReal32 x |> unpack
let complex (x:complex) = Value.fromComplex x |> unpack
let complex32 (x:complex32) = Value.fromComplex32 x |> unpack
let rational (x:BigRational) = Number x

let negate a = Value.negate a |> unpack
Expand Down Expand Up @@ -146,6 +148,11 @@ module Operators =

let real floatingPoint = Values.real floatingPoint

let fromReal floatingPoint = Values.real floatingPoint
let fromReal32 floatingPoint = Values.real32 floatingPoint
let fromComplex floatingPoint = Values.complex floatingPoint
let fromComplex32 floatingPoint = Values.complex32 floatingPoint

let fromInt32 (x:int) = Number (BigRational.FromInt x)
let fromInt64 (x:int64) = Number (BigRational.FromBigInt (BigInteger(x)))
let fromInteger (x:BigInteger) = Number (BigRational.FromBigInt x)
Expand Down Expand Up @@ -870,7 +877,10 @@ type Expression with
static member FromIntegerFraction (n:BigInteger, d:BigInteger) = Operators.fromIntegerFraction n d
static member FromRational (x:BigRational) = Operators.fromRational x
static member Symbol (name:string) = Operators.symbol name
static member Real (floatingPoint:float) = Operators.real floatingPoint
static member Real (floatingPoint:float) = Operators.fromReal floatingPoint
static member Real32 (floatingPoint:float32) = Operators.fromReal32 floatingPoint
static member Complex (floatingPoint:complex) = Operators.fromComplex floatingPoint
static member Complex32 (floatingPoint:complex32) = Operators.fromComplex32 floatingPoint

static member I = Constant I
static member E = Constant E
Expand Down Expand Up @@ -954,21 +964,48 @@ type Expression with
static member Pow (x, (y:int)) = Operators.pow x (Operators.number y)

// Simpler usage - approximations
static member ( + ) (x, (y:float)) = x + (Operators.real y)
static member ( + ) ((x:float), y) = (Operators.real x) + y
static member ( - ) (x, (y:float)) = x - (Operators.real y)
static member ( - ) ((x:float), y) = (Operators.real x) - y
static member ( * ) (x, (y:float)) = x * (Operators.real y)
static member ( * ) ((x:float), y) = (Operators.real x) * y
static member ( / ) (x, (y:float)) = x / (Operators.real y)
static member ( / ) ((x:float), y) = (Operators.real x) / y
static member ( + ) (x, (y:float)) = x + (Operators.fromReal y)
static member ( + ) ((x:float), y) = (Operators.fromReal x) + y
static member ( - ) (x, (y:float)) = x - (Operators.fromReal y)
static member ( - ) ((x:float), y) = (Operators.fromReal x) - y
static member ( * ) (x, (y:float)) = x * (Operators.fromReal y)
static member ( * ) ((x:float), y) = (Operators.fromReal x) * y
static member ( / ) (x, (y:float)) = x / (Operators.fromReal y)
static member ( / ) ((x:float), y) = (Operators.fromReal x) / y
static member ( + ) (x, (y:float32)) = x + (Operators.fromReal32 y)
static member ( + ) ((x:float32), y) = (Operators.fromReal32 x) + y
static member ( - ) (x, (y:float32)) = x - (Operators.fromReal32 y)
static member ( - ) ((x:float32), y) = (Operators.fromReal32 x) - y
static member ( * ) (x, (y:float32)) = x * (Operators.fromReal32 y)
static member ( * ) ((x:float32), y) = (Operators.fromReal32 x) * y
static member ( / ) (x, (y:float32)) = x / (Operators.fromReal32 y)
static member ( / ) ((x:float32), y) = (Operators.fromReal32 x) / y
static member ( + ) (x, (y:complex)) = x + (Operators.fromComplex y)
static member ( + ) ((x:complex), y) = (Operators.fromComplex x) + y
static member ( - ) (x, (y:complex)) = x - (Operators.fromComplex y)
static member ( - ) ((x:complex), y) = (Operators.fromComplex x) - y
static member ( * ) (x, (y:complex)) = x * (Operators.fromComplex y)
static member ( * ) ((x:complex), y) = (Operators.fromComplex x) * y
static member ( / ) (x, (y:complex)) = x / (Operators.fromComplex y)
static member ( / ) ((x:complex), y) = (Operators.fromComplex x) / y
static member ( + ) (x, (y:complex32)) = x + (Operators.fromComplex32 y)
static member ( + ) ((x:complex32), y) = (Operators.fromComplex32 x) + y
static member ( - ) (x, (y:complex32)) = x - (Operators.fromComplex32 y)
static member ( - ) ((x:complex32), y) = (Operators.fromComplex32 x) - y
static member ( * ) (x, (y:complex32)) = x * (Operators.fromComplex32 y)
static member ( * ) ((x:complex32), y) = (Operators.fromComplex32 x) * y
static member ( / ) (x, (y:complex32)) = x / (Operators.fromComplex32 y)
static member ( / ) ((x:complex32), y) = (Operators.fromComplex32 x) / y

// Simpler usage in C#
static member op_Implicit (x:int) = Operators.fromInt32(x)
static member op_Implicit (x:int64) = Operators.fromInt64(x)
static member op_Implicit (x:BigInteger) = Operators.fromInteger(x)
static member op_Implicit (x:BigRational) = Operators.fromRational(x)
static member op_Implicit (x:float) = Operators.real x
static member op_Implicit (x:float) = Operators.fromReal x
static member op_Implicit (x:float32) = Operators.fromReal32 x
static member op_Implicit (x:complex) = Operators.fromComplex x
static member op_Implicit (x:complex32) = Operators.fromComplex32 x


[<RequireQualifiedAccess>]
Expand Down
7 changes: 7 additions & 0 deletions src/Symbolics/SymbolicExpression.fs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ type SymbolicExpression(expression:Expression) =

// LEAFS - Approximations
static member Real(approximation:float) = SymbolicExpression(Expression.Real(approximation))
static member Real32(approximation:float32) = SymbolicExpression(Expression.Real32(approximation))
static member Complex(approximation:complex) = SymbolicExpression(Expression.Complex(approximation))
static member Complex32(approximation:complex32) = SymbolicExpression(Expression.Complex32(approximation))

// LEAFS - Constants
static member I = SymbolicExpression(Expression.I)
Expand Down Expand Up @@ -167,7 +170,11 @@ type SymbolicExpression(expression:Expression) =
static member op_Implicit (x:int64) : SymbolicExpression = SymbolicExpression.FromInt64(x)
static member op_Implicit (x:BigInteger) : SymbolicExpression = SymbolicExpression.FromInteger(x)
static member op_Implicit (x:BigRational) : SymbolicExpression = SymbolicExpression.FromRational(x)

static member op_Implicit (x:float) : SymbolicExpression = SymbolicExpression.Real(x)
static member op_Implicit (x:float32) : SymbolicExpression = SymbolicExpression.Real32(x)
static member op_Implicit (x:complex) : SymbolicExpression = SymbolicExpression.Complex(x)
static member op_Implicit (x:complex32) : SymbolicExpression = SymbolicExpression.Complex32(x)

// bad idea, don't do this
// static member op_Implicit (x:SymbolicExpression) : Expression = x.Expression
Expand Down
26 changes: 19 additions & 7 deletions src/Symbolics/Value.fs
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,33 @@ type Value =
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Value =

let real (x:float) =
let fromReal (x:float) =
if Double.IsPositiveInfinity x then Value.PositiveInfinity
elif Double.IsNegativeInfinity x then Value.NegativeInfinity
elif Double.IsNaN x then Value.Undefined
else Value.Approximation (Approximation.Real x)
else Value.Approximation (Approximation.fromReal x)

let complex (x:complex) =
if x.IsReal() then real x.Real
let fromReal32 (x:float32) =
if Single.IsPositiveInfinity x then Value.PositiveInfinity
elif Single.IsNegativeInfinity x then Value.NegativeInfinity
elif Single.IsNaN x then Value.Undefined
else Value.Approximation (Approximation.fromReal32 x)

let fromComplex (x:complex) =
if x.IsReal() then fromReal x.Real
elif x.IsInfinity() then Value.ComplexInfinity
elif x.IsNaN() then Value.Undefined
else Value.Approximation (Approximation.fromComplex x)

let fromComplex32 (x:complex32) =
if x.IsReal() then fromReal32 x.Real
elif x.IsInfinity() then Value.ComplexInfinity
elif x.IsNaN() then Value.Undefined
else Value.Approximation (Approximation.Complex x)
else Value.Approximation (Approximation.fromComplex32 x)

let approx = function
| Real d -> real d
| Complex c -> complex c
| Real d -> fromReal d
| Complex c -> fromComplex c

let zero = Value.Number (BigRational.Zero)
let one = Value.Number (BigRational.One)
Expand Down

0 comments on commit 15b800a

Please sign in to comment.