forked from tsai/mathnet-numerics
13 changed files with 1711 additions and 0 deletions
@ -1,5 +1,6 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<repositories> |
|||
<repository path="..\src\FSharpUnitTests\packages.config" /> |
|||
<repository path="..\src\Numerics.IO\packages.config" /> |
|||
<repository path="..\src\UnitTests\packages.config" /> |
|||
</repositories> |
|||
@ -0,0 +1,98 @@ |
|||
namespace MathNet.Numerics |
|||
|
|||
#nowarn "40" |
|||
|
|||
open System |
|||
open System.Collections |
|||
open System.Collections.Generic |
|||
|
|||
module Distribution = |
|||
|
|||
type 'a Outcome = { |
|||
Value: 'a |
|||
Probability : BigRational } |
|||
|
|||
type 'a Distribution = 'a Outcome seq |
|||
|
|||
// P(A AND B) = P(A | B) * P(B) |
|||
let bind (f: 'a -> 'b Distribution) (dist:'a Distribution) = |
|||
dist |
|||
|> Seq.map (fun p1 -> |
|||
f p1.Value |
|||
|> Seq.map (fun p2 -> |
|||
{ Value = p2.Value; |
|||
Probability = |
|||
p1.Probability * p2.Probability})) |
|||
|> Seq.concat : 'b Distribution |
|||
|
|||
/// Sequentially compose two actions, passing any value produced by the first as an argument to the second. |
|||
let inline (>>=) dist f = bind f dist |
|||
/// Flipped >>= |
|||
let inline (=<<) f dist = bind f dist |
|||
|
|||
/// Inject a value into the Distribution type |
|||
let returnM (value:'a) = |
|||
Seq.singleton { Value = value ; Probability = 1N/1N } |
|||
: 'a Distribution |
|||
|
|||
type DistributionMonadBuilder() = |
|||
member this.Bind (r, f) = bind f r |
|||
member this.Return x = returnM x |
|||
member this.ReturnFrom x = x |
|||
|
|||
let distribution = DistributionMonadBuilder() |
|||
|
|||
// Create some helpers |
|||
let toUniformDistribution seq : 'a Distribution = |
|||
let l = Seq.length seq |
|||
seq |
|||
|> Seq.map (fun e -> |
|||
{ Value = e; |
|||
Probability = 1N / bignum.FromInt l }) |
|||
|
|||
let probability (dist:'a Distribution) = |
|||
dist |
|||
|> Seq.map (fun o -> o.Probability) |
|||
|> Seq.sum |
|||
|
|||
let certainly = returnM |
|||
let impossible<'a> :'a Distribution = toUniformDistribution [] |
|||
|
|||
let fairDice sides = toUniformDistribution [1..sides] |
|||
|
|||
type CoinSide = |
|||
| Heads |
|||
| Tails |
|||
|
|||
let fairCoin = toUniformDistribution [Heads; Tails] |
|||
|
|||
let filter predicate (dist:'a Distribution) : 'a Distribution = |
|||
dist |> Seq.filter (fun o -> predicate o.Value) |
|||
|
|||
let filterInAnyOrder items dist = |
|||
items |
|||
|> Seq.fold (fun d item -> filter (Seq.exists ((=) (item))) d) dist |
|||
|
|||
/// Transforms a Distribution value by using a specified mapping function. |
|||
let map f (dist:'a Distribution) : 'b Distribution = |
|||
dist |
|||
|> Seq.map (fun o -> { Value = f o.Value; Probability = o.Probability }) |
|||
|
|||
let selectOne values = |
|||
[for e in values -> e,values |> Seq.filter ((<>) e)] |
|||
|> toUniformDistribution |
|||
|
|||
let rec selectMany n values = |
|||
match n with |
|||
| 0 -> certainly ([],values) |
|||
| _ -> |
|||
distribution { |
|||
let! (x,c1) = selectOne values |
|||
let! (xs,c2) = selectMany (n-1) c1 |
|||
return x::xs,c2} |
|||
|
|||
let select n values = |
|||
selectMany n values |
|||
|> map (fst >> List.rev) |
|||
|
|||
let remove items = Seq.filter (fun v -> Seq.forall ((<>) v) items) |
|||
@ -0,0 +1,133 @@ |
|||
// 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 |
|||
open System |
|||
open System.Globalization |
|||
|
|||
[<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 |
|||
|
|||
[<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 |
|||
static member ( * ) (a,b) = Complex.mul a b |
|||
static member ( / ) (a,b) = Complex.div a b |
|||
static member ( ~- ) a = Complex.neg a |
|||
static member ( * ) (a,b) = Complex.smul a b |
|||
static member ( * ) (a,b) = Complex.muls a b |
|||
|
|||
|
|||
module ComplexTopLevelOperators = |
|||
let complex x y = Complex.mkRect (x,y) |
|||
|
|||
@ -0,0 +1,139 @@ |
|||
// 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 |
|||
|
|||
open System |
|||
|
|||
/// The type of complex numbers stored as pairs of 64-bit floating point numbers in rectangular coordinates |
|||
[<Struct>] |
|||
[<CustomEquality; CustomComparison>] |
|||
type Complex = |
|||
/// 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 |
|||
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 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 |
|||
val exp : Complex -> Complex |
|||
/// log(x) is natural log (base e) |
|||
val log : Complex -> Complex |
|||
/// sqrt(x) and 0 <= phase(x) < pi |
|||
val sqrt : Complex -> Complex |
|||
/// Sine |
|||
val sin : Complex -> Complex |
|||
/// Cosine |
|||
val cos : Complex -> Complex |
|||
/// Tagent |
|||
val tan : Complex -> Complex |
|||
|
|||
|
|||
[<AutoOpen>] |
|||
module ComplexTopLevelOperators = |
|||
/// Constructs a complex number from both the real and imaginary part. |
|||
val complex : float -> float -> complex |
|||
|
|||
|
|||
|
|||
@ -0,0 +1,309 @@ |
|||
// First version copied from the F# Power Pack |
|||
// https://raw.github.com/fsharp/powerpack/master/src/FSharp.PowerPack/math/q.fs |
|||
|
|||
|
|||
// (c) Microsoft Corporation. All rights reserved |
|||
|
|||
#nowarn "44" // OK to use the "compiler only" function RangeGeneric |
|||
#nowarn "52" // The value has been copied to ensure the original is not mutated by this operation |
|||
|
|||
namespace MathNet.Numerics |
|||
|
|||
open System |
|||
open System.Numerics |
|||
open System.Globalization |
|||
|
|||
module BigRationalLargeImpl = |
|||
let ZeroI = new BigInteger(0) |
|||
let OneI = new BigInteger(1) |
|||
let bigint (x:int) = new BigInteger(x) |
|||
let ToDoubleI (x:BigInteger) = double x |
|||
let ToInt32I (x:BigInteger) = int32 x |
|||
|
|||
open BigRationalLargeImpl |
|||
|
|||
[<CustomEquality; CustomComparison>] |
|||
type BigRationalLarge = |
|||
| Q of BigInteger * BigInteger // invariants: (p,q) in lowest form, q >= 0 |
|||
|
|||
override n.ToString() = |
|||
let (Q(p,q)) = n |
|||
if q.IsOne then p.ToString() |
|||
else p.ToString() + "/" + q.ToString() |
|||
|
|||
|
|||
static member Hash (Q(ap,aq)) = |
|||
// This hash code must be identical to the hash for BigInteger when the numbers coincide. |
|||
if aq.IsOne then ap.GetHashCode() else (ap.GetHashCode() <<< 3) + aq.GetHashCode() |
|||
|
|||
|
|||
override x.GetHashCode() = BigRationalLarge.Hash(x) |
|||
|
|||
static member Equals(Q(ap,aq), Q(bp,bq)) = |
|||
BigInteger.(=) (ap,bp) && BigInteger.(=) (aq,bq) // normal form, so structural equality |
|||
|
|||
static member LessThan(Q(ap,aq), Q(bp,bq)) = |
|||
BigInteger.(<) (ap * bq,bp * aq) |
|||
|
|||
// note: performance improvement possible here |
|||
static member Compare(p,q) = |
|||
if BigRationalLarge.LessThan(p,q) then -1 |
|||
elif BigRationalLarge.LessThan(q,p)then 1 |
|||
else 0 |
|||
|
|||
interface System.IComparable with |
|||
member this.CompareTo(obj:obj) = |
|||
match obj with |
|||
| :? BigRationalLarge as that -> BigRationalLarge.Compare(this,that) |
|||
| _ -> invalidArg "obj" "the object does not have the correct type" |
|||
|
|||
override this.Equals(that:obj) = |
|||
match that with |
|||
| :? BigRationalLarge as that -> BigRationalLarge.Equals(this,that) |
|||
| _ -> false |
|||
|
|||
member x.IsNegative = let (Q(ap,_)) = x in sign ap < 0 |
|||
member x.IsPositive = let (Q(ap,_)) = x in sign ap > 0 |
|||
|
|||
member x.Numerator = let (Q(p,_)) = x in p |
|||
member x.Denominator = let (Q(_,q)) = x in q |
|||
member x.Sign = (let (Q(p,_)) = x in sign p) |
|||
|
|||
static member ToDouble (Q(p,q)) = |
|||
ToDoubleI p / ToDoubleI q |
|||
|
|||
static member Normalize (p:BigInteger,q:BigInteger) = |
|||
if q.IsZero then |
|||
raise (System.DivideByZeroException()) (* throw for any x/0 *) |
|||
elif q.IsOne then |
|||
Q(p,q) |
|||
else |
|||
let k = BigInteger.GreatestCommonDivisor(p,q) |
|||
let p = p / k |
|||
let q = q / k |
|||
if sign q < 0 then Q(-p,-q) else Q(p,q) |
|||
|
|||
static member Rational (p:int,q:int) = BigRationalLarge.Normalize (bigint p,bigint q) |
|||
static member RationalZ (p,q) = BigRationalLarge.Normalize (p,q) |
|||
|
|||
static member Parse (str:string) = |
|||
let len = str.Length |
|||
if len=0 then invalidArg "str" "empty string"; |
|||
let j = str.IndexOf '/' |
|||
if j >= 0 then |
|||
let p = BigInteger.Parse (str.Substring(0,j)) |
|||
let q = BigInteger.Parse (str.Substring(j+1,len-j-1)) |
|||
BigRationalLarge.RationalZ (p,q) |
|||
else |
|||
let p = BigInteger.Parse str |
|||
BigRationalLarge.RationalZ (p,OneI) |
|||
|
|||
static member (~-) (Q(bp,bq)) = Q(-bp,bq) // still coprime, bq >= 0 |
|||
static member (+) (Q(ap,aq),Q(bp,bq)) = BigRationalLarge.Normalize ((ap * bq) + (bp * aq),aq * bq) |
|||
static member (-) (Q(ap,aq),Q(bp,bq)) = BigRationalLarge.Normalize ((ap * bq) - (bp * aq),aq * bq) |
|||
static member (*) (Q(ap,aq),Q(bp,bq)) = BigRationalLarge.Normalize (ap * bp,aq * bq) |
|||
static member (/) (Q(ap,aq),Q(bp,bq)) = BigRationalLarge.Normalize (ap * bq,aq * bp) |
|||
static member ( ~+ )(n1:BigRationalLarge) = n1 |
|||
|
|||
|
|||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] |
|||
module BigRationalLarge = |
|||
open System.Numerics |
|||
|
|||
let inv (Q(ap,aq)) = BigRationalLarge.Normalize(aq,ap) |
|||
|
|||
let pown (Q(p,q)) (n:int) = Q(BigInteger.Pow(p,n),BigInteger.Pow (q,n)) // p,q powers still coprime |
|||
|
|||
let equal (Q(ap,aq)) (Q(bp,bq)) = ap=bp && aq=bq // normal form, so structural equality |
|||
let lt a b = BigRationalLarge.LessThan(a,b) |
|||
let gt a b = BigRationalLarge.LessThan(b,a) |
|||
let lte (Q(ap,aq)) (Q(bp,bq)) = BigInteger.(<=) (ap * bq,bp * aq) |
|||
let gte (Q(ap,aq)) (Q(bp,bq)) = BigInteger.(>=) (ap * bq,bp * aq) |
|||
|
|||
let of_bigint z = BigRationalLarge.RationalZ(z,OneI ) |
|||
let of_int n = BigRationalLarge.Rational(n,1) |
|||
|
|||
// integer part |
|||
let integer (Q(p,q)) = |
|||
let mutable r = BigInteger(0) |
|||
let d = BigInteger.DivRem (p,q,&r) // have p = d.q + r, |r| < |q| |
|||
if r < ZeroI |
|||
then d - OneI // p = (d-1).q + (r+q) |
|||
else d // p = d.q + r |
|||
|
|||
|
|||
//---------------------------------------------------------------------------- |
|||
// BigRational |
|||
//-------------------------------------------------------------------------- |
|||
|
|||
[<CustomEquality; CustomComparison>] |
|||
[<StructuredFormatDisplay("{StructuredDisplayString}N")>] |
|||
type BigRational = |
|||
| Z of BigInteger |
|||
| Q of BigRationalLarge |
|||
|
|||
static member ( + )(n1,n2) = |
|||
match n1,n2 with |
|||
| Z z ,Z zz -> Z (z + zz) |
|||
| Q q ,Q qq -> Q (q + qq) |
|||
| Z z ,Q qq -> Q (BigRationalLarge.of_bigint z + qq) |
|||
| Q q ,Z zz -> Q (q + BigRationalLarge.of_bigint zz) |
|||
|
|||
static member ( * )(n1,n2) = |
|||
match n1,n2 with |
|||
| Z z ,Z zz -> Z (z * zz) |
|||
| Q q ,Q qq -> Q (q * qq) |
|||
| Z z ,Q qq -> Q (BigRationalLarge.of_bigint z * qq) |
|||
| Q q ,Z zz -> Q (q * BigRationalLarge.of_bigint zz) |
|||
|
|||
static member ( - )(n1,n2) = |
|||
match n1,n2 with |
|||
| Z z ,Z zz -> Z (z - zz) |
|||
| Q q ,Q qq -> Q (q - qq) |
|||
| Z z ,Q qq -> Q (BigRationalLarge.of_bigint z - qq) |
|||
| Q q ,Z zz -> Q (q - BigRationalLarge.of_bigint zz) |
|||
|
|||
static member ( / )(n1,n2) = |
|||
match n1,n2 with |
|||
| Z z ,Z zz -> Q (BigRationalLarge.RationalZ(z,zz)) |
|||
| Q q ,Q qq -> Q (q / qq) |
|||
| Z z ,Q qq -> Q (BigRationalLarge.of_bigint z / qq) |
|||
| Q q ,Z zz -> Q (q / BigRationalLarge.of_bigint zz) |
|||
|
|||
static member ( ~- )(n1) = |
|||
match n1 with |
|||
| Z z -> Z (-z) |
|||
| Q q -> Q (-q) |
|||
|
|||
static member ( ~+ )(n1:BigRational) = n1 |
|||
|
|||
// nb. Q and Z hash codes must match up - see notes above |
|||
override n.GetHashCode() = |
|||
match n with |
|||
| Z z -> z.GetHashCode() |
|||
| Q q -> q.GetHashCode() |
|||
|
|||
override this.Equals(obj:obj) = |
|||
match obj with |
|||
| :? BigRational as that -> BigRational.(=)(this, that) |
|||
| _ -> false |
|||
|
|||
interface System.IComparable with |
|||
member n1.CompareTo(obj:obj) = |
|||
match obj with |
|||
| :? BigRational as n2 -> |
|||
if BigRational.(<)(n1, n2) then -1 elif BigRational.(=)(n1, n2) then 0 else 1 |
|||
| _ -> invalidArg "obj" "the objects are not comparable" |
|||
|
|||
static member FromInt (x:int) = Z (bigint x) |
|||
static member FromBigInt x = Z x |
|||
|
|||
static member Zero = BigRational.FromInt(0) |
|||
static member One = BigRational.FromInt(1) |
|||
|
|||
|
|||
static member PowN (n,i:int) = |
|||
match n with |
|||
| Z z -> Z (BigInteger.Pow (z,i)) |
|||
| Q q -> Q (BigRationalLarge.pown q i) |
|||
|
|||
static member op_Equality (n,nn) = |
|||
match n,nn with |
|||
| Z z ,Z zz -> BigInteger.(=) (z,zz) |
|||
| Q q ,Q qq -> (BigRationalLarge.equal q qq) |
|||
| Z z ,Q qq -> (BigRationalLarge.equal (BigRationalLarge.of_bigint z) qq) |
|||
| Q q ,Z zz -> (BigRationalLarge.equal q (BigRationalLarge.of_bigint zz)) |
|||
static member op_Inequality (n,nn) = not (BigRational.op_Equality(n,nn)) |
|||
|
|||
static member op_LessThan (n,nn) = |
|||
match n,nn with |
|||
| Z z ,Z zz -> BigInteger.(<) (z,zz) |
|||
| Q q ,Q qq -> (BigRationalLarge.lt q qq) |
|||
| Z z ,Q qq -> (BigRationalLarge.lt (BigRationalLarge.of_bigint z) qq) |
|||
| Q q ,Z zz -> (BigRationalLarge.lt q (BigRationalLarge.of_bigint zz)) |
|||
static member op_GreaterThan (n,nn) = |
|||
match n,nn with |
|||
| Z z ,Z zz -> BigInteger.(>) (z,zz) |
|||
| Q q ,Q qq -> (BigRationalLarge.gt q qq) |
|||
| Z z ,Q qq -> (BigRationalLarge.gt (BigRationalLarge.of_bigint z) qq) |
|||
| Q q ,Z zz -> (BigRationalLarge.gt q (BigRationalLarge.of_bigint zz)) |
|||
static member op_LessThanOrEqual (n,nn) = |
|||
match n,nn with |
|||
| Z z ,Z zz -> BigInteger.(<=) (z,zz) |
|||
| Q q ,Q qq -> (BigRationalLarge.lte q qq) |
|||
| Z z ,Q qq -> (BigRationalLarge.lte (BigRationalLarge.of_bigint z) qq) |
|||
| Q q ,Z zz -> (BigRationalLarge.lte q (BigRationalLarge.of_bigint zz)) |
|||
static member op_GreaterThanOrEqual (n,nn) = |
|||
match n,nn with |
|||
| Z z ,Z zz -> BigInteger.(>=) (z,zz) |
|||
| Q q ,Q qq -> (BigRationalLarge.gte q qq) |
|||
| Z z ,Q qq -> (BigRationalLarge.gte (BigRationalLarge.of_bigint z) qq) |
|||
| Q q ,Z zz -> (BigRationalLarge.gte q (BigRationalLarge.of_bigint zz)) |
|||
|
|||
|
|||
member n.IsNegative = |
|||
match n with |
|||
| Z z -> sign z < 0 |
|||
| Q q -> q.IsNegative |
|||
|
|||
member n.IsPositive = |
|||
match n with |
|||
| Z z -> sign z > 0 |
|||
| Q q -> q.IsPositive |
|||
|
|||
member n.Numerator = |
|||
match n with |
|||
| Z z -> z |
|||
| Q q -> q.Numerator |
|||
|
|||
member n.Denominator = |
|||
match n with |
|||
| Z _ -> OneI |
|||
| Q q -> q.Denominator |
|||
|
|||
member n.Sign = |
|||
if n.IsNegative then -1 |
|||
elif n.IsPositive then 1 |
|||
else 0 |
|||
|
|||
static member Abs(n:BigRational) = |
|||
if n.IsNegative then -n else n |
|||
|
|||
static member ToDouble(n:BigRational) = |
|||
match n with |
|||
| Z z -> ToDoubleI z |
|||
| Q q -> BigRationalLarge.ToDouble q |
|||
|
|||
static member ToBigInt(n:BigRational) = |
|||
match n with |
|||
| Z z -> z |
|||
| Q q -> BigRationalLarge.integer q |
|||
|
|||
static member ToInt32(n:BigRational) = |
|||
match n with |
|||
| Z z -> ToInt32I(z) |
|||
| Q q -> ToInt32I(BigRationalLarge.integer q ) |
|||
|
|||
static member op_Explicit (n:BigRational) = BigRational.ToInt32 n |
|||
static member op_Explicit (n:BigRational) = BigRational.ToDouble n |
|||
static member op_Explicit (n:BigRational) = BigRational.ToBigInt n |
|||
|
|||
|
|||
override n.ToString() = |
|||
match n with |
|||
| Z z -> z.ToString() |
|||
| Q q -> q.ToString() |
|||
|
|||
member x.StructuredDisplayString = x.ToString() |
|||
|
|||
static member Parse(s:string) = Q (BigRationalLarge.Parse s) |
|||
|
|||
type BigNum = BigRational |
|||
type bignum = BigNum |
|||
|
|||
module NumericLiteralN = |
|||
let FromZero () = BigRational.Zero |
|||
let FromOne () = BigRational.One |
|||
let FromInt32 i = BigRational.FromInt i |
|||
let FromInt64 (i64:int64) = BigRational.FromBigInt (new BigInteger(i64)) |
|||
let FromString s = BigRational.Parse s |
|||
@ -0,0 +1,96 @@ |
|||
// First version copied from the F# Power Pack |
|||
// https://raw.github.com/fsharp/powerpack/master/src/FSharp.PowerPack/math/q.fsi |
|||
|
|||
|
|||
// (c) Microsoft Corporation 2005-2009. |
|||
|
|||
namespace MathNet.Numerics |
|||
|
|||
open System |
|||
open System.Numerics |
|||
|
|||
/// The type of arbitrary-sized rational numbers |
|||
[<Sealed>] |
|||
type BigRational = |
|||
/// Return the sum of two rational numbers |
|||
static member ( + ) : BigRational * BigRational -> BigRational |
|||
/// Return the product of two rational numbers |
|||
static member ( * ) : BigRational * BigRational -> BigRational |
|||
/// Return the difference of two rational numbers |
|||
static member ( - ) : BigRational * BigRational -> BigRational |
|||
/// Return the ratio of two rational numbers |
|||
static member ( / ) : BigRational * BigRational -> BigRational |
|||
/// Return the negation of a rational number |
|||
static member ( ~- ): BigRational -> BigRational |
|||
/// Return the given rational number |
|||
static member ( ~+ ): BigRational -> BigRational |
|||
|
|||
override ToString: unit -> string |
|||
override GetHashCode: unit -> int |
|||
interface System.IComparable |
|||
|
|||
/// Get zero as a rational number |
|||
static member Zero : BigRational |
|||
/// Get one as a rational number |
|||
static member One : BigRational |
|||
/// This operator is for use from other .NET languages |
|||
static member op_Equality : BigRational * BigRational -> bool |
|||
/// This operator is for use from other .NET languages |
|||
static member op_Inequality : BigRational * BigRational -> bool |
|||
/// This operator is for use from other .NET languages |
|||
static member op_LessThan: BigRational * BigRational -> bool |
|||
/// This operator is for use from other .NET languages |
|||
static member op_GreaterThan: BigRational * BigRational -> bool |
|||
/// This operator is for use from other .NET languages |
|||
static member op_LessThanOrEqual: BigRational * BigRational -> bool |
|||
/// This operator is for use from other .NET languages |
|||
static member op_GreaterThanOrEqual: BigRational * BigRational -> bool |
|||
|
|||
/// Return a boolean indicating if this rational number is strictly negative |
|||
member IsNegative: bool |
|||
/// Return a boolean indicating if this rational number is strictly positive |
|||
member IsPositive: bool |
|||
|
|||
/// Return the numerator of the normalized rational number |
|||
member Numerator: BigInteger |
|||
/// Return the denominator of the normalized rational number |
|||
member Denominator: BigInteger |
|||
|
|||
member StructuredDisplayString : string |
|||
|
|||
/// Return the absolute value of a rational number |
|||
static member Abs : BigRational -> BigRational |
|||
/// Return the sign of a rational number; 0, +1 or -1 |
|||
member Sign : int |
|||
/// Return the result of raising the given rational number to the given power |
|||
static member PowN : BigRational * int -> BigRational |
|||
/// Return the result of converting the given integer to a rational number |
|||
static member FromInt : int -> BigRational |
|||
/// Return the result of converting the given big integer to a rational number |
|||
static member FromBigInt : BigInteger -> BigRational |
|||
/// Return the result of converting the given rational number to a floating point number |
|||
static member ToDouble: BigRational -> float |
|||
/// Return the result of converting the given rational number to a big integer |
|||
static member ToBigInt: BigRational -> BigInteger |
|||
/// Return the result of converting the given rational number to an integer |
|||
static member ToInt32 : BigRational -> int |
|||
/// Return the result of converting the given rational number to a floating point number |
|||
static member op_Explicit : BigRational -> float |
|||
/// Return the result of converting the given rational number to a big integer |
|||
static member op_Explicit : BigRational -> BigInteger |
|||
/// Return the result of converting the given rational number to an integer |
|||
static member op_Explicit : BigRational -> int |
|||
/// Return the result of converting the string to a rational number |
|||
static member Parse: string -> BigRational |
|||
|
|||
type BigNum = BigRational |
|||
|
|||
type bignum = BigRational |
|||
|
|||
[<RequireQualifiedAccess>] |
|||
module NumericLiteralN = |
|||
val FromZero : unit -> BigRational |
|||
val FromOne : unit -> BigRational |
|||
val FromInt32 : int32 -> BigRational |
|||
val FromInt64 : int64 -> BigRational |
|||
val FromString : string -> BigRational |
|||
@ -0,0 +1,614 @@ |
|||
// First version copied from the F# Power Pack |
|||
// https://raw.github.com/fsharp/powerpack/master/src/FSharp.PowerPack.Unittests/BigRationalTests.fs |
|||
|
|||
namespace MathNet.Numerics.Tests |
|||
|
|||
open MathNet.Numerics |
|||
open NUnit.Framework |
|||
open System |
|||
open System.Collections |
|||
open System.Collections.Generic |
|||
open System.Numerics |
|||
|
|||
|
|||
[<TestFixture>] |
|||
type public BigRationalTests() = |
|||
|
|||
// BigRational Tests |
|||
// ================= |
|||
|
|||
// Notes: What cases to consider? |
|||
// For (p,q) cases q=0, q=1, q<>1. [UPDATE: remove (x,0)] |
|||
// For (p,q) when q=1 there could be 2 internal representations, either Z or Q. |
|||
// For (p,0) this value can be signed, corresponds to +/- infinity point. [Update: remove it] |
|||
// Hashes on (p,1) for both representations must agree. |
|||
// For binary operators, try for result with and without HCF (normalisation). |
|||
// Also: 0/0 is an acceptable representation. See normalisation code. [Update: remove it]. |
|||
|
|||
// Overrides to test: |
|||
// .ToString() |
|||
// .GetHashCode() |
|||
// .Equals() |
|||
// IComparable.CompareTo() |
|||
|
|||
// Misc construction. |
|||
let natA n = BigRational.FromInt n // internally Z |
|||
let natB n = (natA n / natA 7) * natA 7 // internally Q |
|||
let ratio p q = BigRational.FromInt p / BigRational.FromInt q |
|||
let (/%) b c = BigRational.FromBigInt b / BigRational.FromBigInt c |
|||
|
|||
// Misc test values |
|||
let q0 = natA 0 |
|||
let q1 = natA 1 |
|||
let q2 = natA 2 |
|||
let q3 = natA 3 |
|||
let q4 = natA 4 |
|||
let q5 = natA 5 |
|||
let minIntI = bigint System.Int32.MinValue |
|||
let maxIntI = bigint System.Int32.MaxValue |
|||
let ran = System.Random() |
|||
let nextZ n = bigint (ran.Next(n)) |
|||
|
|||
// A selection of test points. |
|||
let points = |
|||
// A selection of integer and reciprical points |
|||
let points = |
|||
[for i in -13I .. 13I -> i,1I] @ |
|||
[for i in -13I .. 13I -> 1I,i] |
|||
// Exclude x/0 |
|||
let points = [for p,q in points do if q <> 0I then yield p,q ] // PROPOSE: (q,0) never a valid Q value, filter them out of tests... |
|||
// Scale by various values, including into BigInt range |
|||
let scale (kp,kq) (p,q) = (p*kp,q*kq) |
|||
let scales k pqs = List.map (scale k) pqs |
|||
let points = List.concat [points; |
|||
scales (10000I,1I) points; |
|||
scales (1I,10000I) points; |
|||
scales (maxIntI,1I) points; |
|||
scales (1I,maxIntI) points; |
|||
] |
|||
points |
|||
let pointsNonZero = [for p,q in points do if p<>0I then yield p,q] // non zero points |
|||
|
|||
let makeQs p q = |
|||
if q = 1I && minIntI <= p && p <= maxIntI then |
|||
// (p,1) where p is int32 |
|||
let p32 = int32 p |
|||
[natA p32;natB p32;BigRational.FromBigInt p] // two reprs for int32 |
|||
else |
|||
[BigRational.FromBigInt p / BigRational.FromBigInt q] |
|||
|
|||
let miscQs = [for p,q in points do yield! makeQs p q] |
|||
|
|||
let product xs ys = [for x in xs do for y in ys do yield x,y] |
|||
let vector1s = [for z in points -> z] |
|||
let vector2s = product points points |
|||
|
|||
[<Test>] |
|||
member this.BasicTests1() = |
|||
check "generic format h" "1N" (sprintf "%A" 1N) |
|||
check "generic format q" "-1N" (sprintf "%A" (-1N)) |
|||
|
|||
test "vliwe98" (id -2N = - 2N) |
|||
test "d3oc002" (LanguagePrimitives.GenericZero<bignum> = 0N) |
|||
test "d3oc112w" (LanguagePrimitives.GenericOne<bignum> = 1N) |
|||
|
|||
check "weioj3h" (sprintf "%O" 3N) "3" |
|||
check "weioj3k" (sprintf "%O" (3N / 4N)) "3/4" |
|||
check "weioj3k" (sprintf "%O" (3N / 400000000N)) "3/400000000" |
|||
check "weioj3l" (sprintf "%O" (3N / 3N)) "1" |
|||
check "weioj3q" (sprintf "%O" (-3N)) "-3" |
|||
//check "weioj3w" (sprintf "%O" -3N) "-3" |
|||
check "weioj3e" (sprintf "%O" (-3N / -3N)) "1" |
|||
|
|||
// The reason why we do not use hardcoded values is the the representation may change based on the NetFx we are targeting. |
|||
// For example, when targeting NetFx4.0, the result is "-3E+61" instead of "-3000....0N" |
|||
let v = -30000000000000000000000000000000000000000000000000000000000000N |
|||
check "weioj3r" (sprintf "%O" v) ((box v).ToString()) |
|||
|
|||
|
|||
[<Test>] |
|||
member this.BasicTests2() = |
|||
|
|||
|
|||
// Test arithmetic ops: tests |
|||
let test2One name f check ((p,q),(pp,qq)) = |
|||
// There may be several ways to construct the test rationals |
|||
let zs = makeQs p q |
|||
let zzs = makeQs pp qq |
|||
let results = [for z in zs do for zz in zzs do yield f (z,zz)] |
|||
let refP,refQ = check (p,q) (pp,qq) |
|||
let refResult = BigRational.FromBigInt refP / BigRational.FromBigInt refQ |
|||
let resOK (result:BigRational) = |
|||
result.Numerator * refQ = refP * result.Denominator && |
|||
BigRational.Equals(refResult,result) |
|||
match List.tryFind (fun result -> not (resOK result)) results with |
|||
| None -> () // ok |
|||
| Some result -> printf "Test failed. %s (%A,%A) (%A,%A). Expected %A. Observed %A\n" name p q pp qq refResult result |
|||
reportFailure "cejkew09" |
|||
|
|||
let test2All name f check vectors = List.iter (test2One name f check) vectors |
|||
|
|||
// Test arithmetic ops: call |
|||
test2All "add" (BigRational.(+)) (fun (p,q) (pp,qq) -> (p*qq + q*pp,q*qq)) vector2s |
|||
test2All "sub" (BigRational.(-)) (fun (p,q) (pp,qq) -> (p*qq - q*pp,q*qq)) vector2s |
|||
test2All "mul" (BigRational.(*)) (fun (p,q) (pp,qq) -> (p*pp,q*qq)) vector2s // *) <-- for EMACS |
|||
test2All "div" (BigRational.(/)) (fun (p,q) (pp,qq) -> (p*qq,q*pp)) (product points pointsNonZero) |
|||
|
|||
|
|||
|
|||
[<Test>] |
|||
member this.RangeTests() = |
|||
// Test x0 .. dx .. x1 |
|||
let checkRange3 (x0:BigRational) dx x1 k = |
|||
let f (x:BigRational) = x * BigRational.FromBigInt k |> BigRational.ToBigInt |
|||
let rangeA = {x0 .. dx .. x1} |> Seq.map f |
|||
let rangeB = {f x0 .. f dx .. f x1} |
|||
//printf "Length=%d\n" (Seq.length rangeA) |
|||
let same = Seq.forall2 (=) rangeA rangeB |
|||
check (sprintf "Range3 %A .. %A .. %A scaled to %A" x0 dx x1 k) same true |
|||
|
|||
checkRange3 (0I /% 1I) (1I /% 7I) (100I /% 1I) (7I*1I) |
|||
checkRange3 (0I /% 1I) (1I /% 7I) (100I /% 11I) (7I*11I) |
|||
checkRange3 (1I /% 13I) (1I /% 7I) (100I /% 11I) (7I*11I*13I) |
|||
for i = 0 to 1000 do |
|||
let m = 1000 // max steps is -m to m in steps of 1/m i.e. 2.m^2 |
|||
let p0,q0 = nextZ m ,nextZ m + 1I |
|||
let p1,q1 = nextZ m ,nextZ m + 1I |
|||
let pd,qd = nextZ m + 1I,nextZ m + 1I |
|||
checkRange3 (p0 /% q0) (pd /% qd) (p1 /% q1) (q0 * q1 * qd) |
|||
|
|||
|
|||
// Test x0 .. x1 |
|||
let checkRange2 (x0:BigRational) x1 = |
|||
let z0 = BigRational.ToBigInt x0 |
|||
let z01 = BigRational.ToBigInt (x1 - x0) |
|||
let f (x:BigRational) = x |> BigRational.ToBigInt |
|||
let rangeA = [x0 .. x1] |> List.map f // range with each item rounded down |
|||
let rangeB = [z0 .. z0 + z01] // range of same length from the round down start point |
|||
check (sprintf "Range2: %A .. %A" x0 x1) rangeA rangeB |
|||
|
|||
checkRange2 (0I /% 1I) (100I /% 1I) |
|||
checkRange2 (0I /% 1I) (100I /% 11I) |
|||
checkRange2 (1I /% 13I) (100I /% 11I) |
|||
for i = 0 to 1000 do |
|||
let m = 10000 // max steps is -m to m in steps of 1 i.e. 2.m |
|||
let p0,q0 = nextZ m ,nextZ m + 1I |
|||
let p1,q1 = nextZ m ,nextZ m + 1I |
|||
checkRange2 (p0 /% q0) (p1 /% q1) //(q0 * q1 * qd) |
|||
|
|||
// ToString() |
|||
// Cases: integer, computed integer, rational<1, rational>1, +/-infinity, nan |
|||
(natA 1).ToString() |> check "ToString" "1" |
|||
(natA 0).ToString() |> check "ToString" "0" |
|||
(natA (-12)).ToString() |> check "ToString" "-12" |
|||
(natB 1).ToString() |> check "ToString" "1" |
|||
(natB 0).ToString() |> check "ToString" "0" |
|||
(natB (-12)).ToString() |> check "ToString" "-12" |
|||
(1I /% 3I).ToString() |> check "ToString" "1/3" |
|||
(12I /% 5I).ToString() |> check "ToString" "12/5" |
|||
//(13I /% 0I).ToString() |> check "ToString" "1/0" // + 1/0. Plan to make this invalid value |
|||
//(-13I /% 0I).ToString() |> check "ToString" "1/0" // - 1/0. Plan to make this invalid value |
|||
//(0I /% 0I).ToString() |> check "ToString" "0/0" // 0/0. Plan to make this invalid value |
|||
|
|||
// GetHashCode |
|||
// Cases: zero, integer, computed integer, computed by multiple routes. |
|||
let checkSameHashGeneric a b = check (sprintf "GenericHash %A %A" a b) (a.GetHashCode()) (b.GetHashCode()) |
|||
let checkSameHash (a:BigRational) (b:BigRational) = check (sprintf "BigRationalHash %A %A" a b) (a.GetHashCode()) (b.GetHashCode()); checkSameHashGeneric a b |
|||
|
|||
List.iter (fun n -> checkSameHash (natA n) (natB n)) [-10 .. 10] |
|||
List.iter (fun n -> checkSameHash n ((n * q3 + n * q2) / q5)) miscQs |
|||
|
|||
// bug 3488: should non-finite values be supported? |
|||
//let x = BigRational.FromBigInt (-1I) / BigRational.FromBigInt 0I |
|||
//let q2,q3,q5 = BigRational.FromInt 2,BigRational.FromInt 3,BigRational.FromInt 5 |
|||
//let x2 = (x * q2 + x * q3) / q5 |
|||
//x,x2,x = x2 |
|||
|
|||
// Test: Zero,One? |
|||
check "ZeroA" BigRational.Zero (natA 0) |
|||
check "ZeroA" BigRational.Zero (natA 0) |
|||
check "OneA" BigRational.One (natB 1) |
|||
check "OneB" BigRational.One (natB 1) |
|||
|
|||
[<Test>] |
|||
member this.BinaryAndUnaryOperators() = |
|||
// Test: generic bop |
|||
let testR2One name f check ((p,q),(pp,qq)) = |
|||
// There may be several ways to construct the test rationals |
|||
let zs = makeQs p q |
|||
let zzs = makeQs pp qq |
|||
let resultRef = check (p,q) (pp,qq) // : bool |
|||
let args = [for z in zs do for zz in zzs do yield (z,zz)] |
|||
match List.tryFind (fun (z,zz) -> resultRef <> f (z,zz)) args with |
|||
| None -> () // ok |
|||
| Some (z,zz) -> printf "Test failed. %s (%A,%A) (%A,%A) = %s %A %A. Expected %A.\n" name p q pp qq name z zz resultRef |
|||
reportFailure "cknwe9" |
|||
|
|||
// Test: generic uop |
|||
let testR1One name f check (p,q) = |
|||
// There may be several ways to construct the test rationals |
|||
let zs = makeQs p q |
|||
let resultRef = check (p,q) //: bool |
|||
match List.tryFind (fun z -> resultRef <> f z) zs with |
|||
| None -> () // ok |
|||
| Some z -> printf "Test failed. %s (%A,%A) = %s %A. Expected %A.\n" name p q name z resultRef |
|||
reportFailure "vekjkrejvre0" |
|||
|
|||
let testR2All name f check vectors = List.iter (testR2One name f check) vectors |
|||
let testR1All name f check vectors = List.iter (testR1One name f check) vectors |
|||
|
|||
// Test: relations |
|||
let sign (i:BigInteger) = BigInteger(i.Sign) |
|||
testR2All "=" BigRational.(=) (fun (p,q) (pp,qq) -> (p*qq = q*pp)) vector2s |
|||
testR2All "=" BigRational.op_Equality (fun (p,q) (pp,qq) -> (p*qq = q*pp)) vector2s |
|||
testR2All "!=" BigRational.op_Inequality (fun (p,q) (pp,qq) -> (p*qq <> q*pp)) vector2s |
|||
// p/q < pp/qq |
|||
// iff (p * sign q) / (q * sign q) < (pp * sign qq) / (qq * sign qq) |
|||
// iff (p * sign q) * (qq * sign qq) < (pp * sign qq) * (q * sign q) since q*sign q is always +ve. |
|||
testR2All "<" BigRational.(<) (fun (p,q) (pp,qq) -> (p * sign q) * (qq * sign qq) < (pp * sign qq) * (q * sign q)) vector2s |
|||
testR2All ">" BigRational.(>) (fun (p,q) (pp,qq) -> (p * sign q) * (qq * sign qq) > (pp * sign qq) * (q * sign q)) vector2s |
|||
testR2All "<=" BigRational.(<=) (fun (p,q) (pp,qq) -> (p * sign q) * (qq * sign qq) <= (pp * sign qq) * (q * sign q)) vector2s |
|||
testR2All ">=" BigRational.(>=) (fun (p,q) (pp,qq) -> (p * sign q) * (qq * sign qq) >= (pp * sign qq) * (q * sign q)) vector2s |
|||
|
|||
// System.IComparable tests |
|||
let BigRationalCompareTo (p:BigRational,q:BigRational) = (p :> System.IComparable).CompareTo(q) |
|||
testR2All "IComparable.CompareTo" BigRationalCompareTo (fun (p,q) (pp,qq) -> compare ((p * sign q) * (qq * sign qq)) ((pp * sign qq) * (q * sign q))) vector2s |
|||
|
|||
// Test: is negative, is positive |
|||
testR1All "IsNegative" (fun (x:BigRational) -> x.IsNegative) (fun (p,q) -> sign p * sign q = -1I) vector1s |
|||
testR1All "IsPositive" (fun (x:BigRational) -> x.IsPositive) (fun (p,q) -> sign p * sign q = 1I) vector1s |
|||
testR1All "IsZero" (fun (x:BigRational) -> x = q0) (fun (p,q) -> sign p = 0I) vector1s |
|||
|
|||
|
|||
let test1One name f check (p,q) = |
|||
// There may be several ways to construct the test rationals |
|||
let zs = makeQs p q |
|||
let results = [for z in zs -> f z] |
|||
let refP,refQ = check (p,q) |
|||
let refResult = BigRational.FromBigInt refP / BigRational.FromBigInt refQ |
|||
let resOK (result:BigRational) = |
|||
result.Numerator * refQ = refP * result.Denominator && |
|||
BigRational.Equals(refResult,result) |
|||
match List.tryFind (fun result -> not (resOK result)) results with |
|||
| None -> () // ok |
|||
| Some result -> printf "Test failed. %s (%A,%A). Expected %A. Observed %A\n" name p q refResult result |
|||
reportFailure "klcwe09wek" |
|||
|
|||
let test1All name f check vectors = List.iter (test1One name f check) vectors |
|||
|
|||
test1All "neg" (BigRational.(~-)) (fun (p,q) -> (-p,q)) vector1s |
|||
test1All "pos" (BigRational.(~+)) (fun (p,q) -> (p,q)) vector1s // why have ~+ ??? |
|||
|
|||
// Test: Abs,Sign |
|||
test1All "Abs" (BigRational.Abs) (fun (p,q) -> (abs p,abs q)) vector1s |
|||
testR1All "Sign" (fun (x:BigRational) -> x.Sign) (fun (p,q) -> check "NonZeroDenom" (sign q <> 0I) true; (sign p * sign q) |> int32) vector1s |
|||
|
|||
// Test: PowN |
|||
test1All "PowN(x,2)" (fun x -> BigRational.PowN(x,2)) (fun (p,q) -> (p*p,q*q)) vector1s |
|||
test1All "PowN(x,1)" (fun x -> BigRational.PowN(x,1)) (fun (p,q) -> (p,q)) vector1s |
|||
test1All "PowN(x,0)" (fun x -> BigRational.PowN(x,0)) (fun (p,q) -> (1I,1I)) vector1s |
|||
|
|||
// MatteoT: moved to numbersVS2008\test.ml |
|||
//test1All "PowN(x,200)" (fun x -> BigRational.PowN(x,200)) (fun (p,q) -> (BigInteger.Pow(p,200I),BigInteger.Pow(q,200I))) vector1s |
|||
|
|||
// MatteoT: moved to numbersVS2008\test.ml |
|||
//let powers = [0I .. 100I] |
|||
//powers |> List.iter (fun i -> test1All "PowN(x,i)" (fun x -> BigRational.PowN(x,int i)) (fun (p,q) -> (BigInteger.Pow(p,i),BigInteger.Pow(q,i))) vector1s) |
|||
|
|||
// Test: PowN with negative powers - expect exception |
|||
testR1All "PowN(x,-1)" (fun x -> throws (fun () -> BigRational.PowN(x,-1))) (fun (p,q) -> true) vector1s |
|||
testR1All "PowN(x,-4)" (fun x -> throws (fun () -> BigRational.PowN(x,-4))) (fun (p,q) -> true) vector1s |
|||
|
|||
|
|||
|
|||
[<TestFixture>] |
|||
type BigNumType() = |
|||
let g_positive1 = 1000000000000000000000000000000000018N |
|||
let g_positive2 = 1000000000000000000000000000000000000N |
|||
let g_negative1 = -1000000000000000000000000000000000018N |
|||
let g_negative2 = -1000000000000000000000000000000000000N |
|||
let g_negative3 = -1000000000000000000000000000000000036N |
|||
let g_zero = 0N |
|||
let g_normal = 88N |
|||
let g_bigintpositive = 1000000000000000000000000000000000018I |
|||
let g_bigintnegative = -1000000000000000000000000000000000018I |
|||
|
|||
// Interfaces |
|||
[<Test>] |
|||
member this.IComparable() = |
|||
// Legit IC |
|||
let ic = g_positive1 :> IComparable |
|||
Assert.AreEqual(ic.CompareTo(g_positive1),0) |
|||
checkThrowsArgumentException( fun () -> ic.CompareTo(g_bigintpositive) |> ignore) |
|||
|
|||
// Base class methods |
|||
[<Test>] |
|||
member this.ObjectToString() = |
|||
|
|||
// Currently the CLR 4.0 and CLR 2.0 behavior of BigInt.ToString is different, causing this test to fail. |
|||
|
|||
Assert.AreEqual(g_positive1.ToString(), |
|||
"1000000000000000000000000000000000018") |
|||
Assert.AreEqual(g_zero.ToString(),"0") |
|||
Assert.AreEqual(g_normal.ToString(),"88") |
|||
|
|||
|
|||
[<Test; Ignore("Bug 5286 - Differences between CLR 2.0 BigInt and CLR 4.0 BigInt")>] |
|||
member this.System_Object_GetHashCode() = |
|||
Assert.AreEqual(g_negative1.GetHashCode(),1210897093) |
|||
Assert.AreEqual(g_normal.GetHashCode(),89) |
|||
Assert.AreEqual(g_zero.GetHashCode(),1) |
|||
() |
|||
|
|||
// Static methods |
|||
[<Test>] |
|||
member this.Abs() = |
|||
Assert.AreEqual(bignum.Abs(g_negative1), g_positive1) |
|||
Assert.AreEqual(bignum.Abs(g_negative2), g_positive2) |
|||
Assert.AreEqual(bignum.Abs(g_positive1), g_positive1) |
|||
Assert.AreEqual(bignum.Abs(g_normal), g_normal) |
|||
Assert.AreEqual(bignum.Abs(g_zero), g_zero) |
|||
() |
|||
|
|||
[<Test>] |
|||
member this.FromBigInt() = |
|||
Assert.AreEqual(bignum.FromBigInt(g_bigintpositive), |
|||
g_positive1) |
|||
Assert.AreEqual(bignum.FromBigInt(g_bigintnegative), |
|||
g_negative1) |
|||
Assert.AreEqual(bignum.FromBigInt(0I),g_zero) |
|||
Assert.AreEqual(bignum.FromBigInt(88I),g_normal) |
|||
() |
|||
|
|||
[<Test>] |
|||
member this.FromInt() = |
|||
Assert.AreEqual(bignum.FromInt(2147483647), 2147483647N) |
|||
Assert.AreEqual(bignum.FromInt(-2147483648), -2147483648N) |
|||
Assert.AreEqual(bignum.FromInt(0), 0N) |
|||
Assert.AreEqual(bignum.FromInt(88), 88N) |
|||
() |
|||
|
|||
[<Test>] |
|||
member this.One() = |
|||
Assert.AreEqual(bignum.One,1N) |
|||
() |
|||
|
|||
[<Test>] |
|||
member this.Parse() = |
|||
Assert.AreEqual(bignum.Parse("100"), 100N) |
|||
Assert.AreEqual(bignum.Parse("-100"), -100N) |
|||
Assert.AreEqual(bignum.Parse("0"), g_zero) |
|||
Assert.AreEqual(bignum.Parse("88"), g_normal) |
|||
() |
|||
|
|||
[<Test>] |
|||
member this.PowN() = |
|||
Assert.AreEqual(bignum.PowN(100N,2), 10000N) |
|||
Assert.AreEqual(bignum.PowN(-3N,3), -27N) |
|||
Assert.AreEqual(bignum.PowN(g_zero,2147483647), 0N) |
|||
Assert.AreEqual(bignum.PowN(g_normal,0), 1N) |
|||
() |
|||
|
|||
|
|||
[<Test>] |
|||
member this.Sign() = |
|||
Assert.AreEqual(g_positive1.Sign, 1) |
|||
Assert.AreEqual(g_negative1.Sign, -1) |
|||
Assert.AreEqual(g_zero.Sign, 0) |
|||
Assert.AreEqual(g_normal.Sign, 1) |
|||
() |
|||
|
|||
|
|||
|
|||
[<Test>] |
|||
member this.ToBigInt() = |
|||
Assert.AreEqual(bignum.ToBigInt(g_positive1), g_bigintpositive) |
|||
Assert.AreEqual(bignum.ToBigInt(g_negative1), g_bigintnegative) |
|||
Assert.AreEqual(bignum.ToBigInt(g_zero), 0I) |
|||
Assert.AreEqual(bignum.ToBigInt(g_normal), 88I) |
|||
() |
|||
|
|||
|
|||
|
|||
[<Test>] |
|||
member this.ToDouble() = |
|||
Assert.AreEqual(bignum.ToDouble(179769N*1000000000000000N), 1.79769E+20) |
|||
Assert.AreEqual(bignum.ToDouble(-179769N*1000000000000000N), -1.79769E+20) |
|||
Assert.AreEqual(bignum.ToDouble(0N),0.0) |
|||
Assert.AreEqual(bignum.ToDouble(88N),88.0) |
|||
Assert.AreEqual(double(179769N*1000000000000000N), 1.79769E+20) |
|||
Assert.AreEqual(double(-179769N*1000000000000000N), -1.79769E+20) |
|||
Assert.AreEqual(double(0N),0.0) |
|||
Assert.AreEqual(double(88N),88.0) |
|||
() |
|||
|
|||
|
|||
[<Test>] |
|||
member this.ToInt32() = |
|||
Assert.AreEqual(bignum.ToInt32(2147483647N), 2147483647) |
|||
Assert.AreEqual(bignum.ToInt32(-2147483648N), -2147483648) |
|||
Assert.AreEqual(bignum.ToInt32(0N), 0) |
|||
Assert.AreEqual(bignum.ToInt32(88N), 88) |
|||
Assert.AreEqual(int32(2147483647N), 2147483647) |
|||
Assert.AreEqual(int32(-2147483648N), -2147483648) |
|||
Assert.AreEqual(int32(0N), 0) |
|||
Assert.AreEqual(int32(88N), 88) |
|||
|
|||
|
|||
|
|||
[<Test>] |
|||
member this.Zero() = |
|||
Assert.AreEqual(bignum.Zero,0N) |
|||
() |
|||
|
|||
// operator methods |
|||
[<Test>] |
|||
member this.test_op_Addition() = |
|||
|
|||
Assert.AreEqual(100N + 200N, 300N) |
|||
Assert.AreEqual((-100N) + (-200N), -300N) |
|||
Assert.AreEqual(g_positive1 + g_negative1, 0N) |
|||
Assert.AreEqual(g_zero + g_zero,0N) |
|||
Assert.AreEqual(g_normal + g_normal, 176N) |
|||
Assert.AreEqual(g_normal + g_normal, 176N) |
|||
() |
|||
|
|||
|
|||
|
|||
[<Test>] |
|||
member this.test_op_Division() = |
|||
Assert.AreEqual(g_positive1 / g_positive1, 1N) |
|||
Assert.AreEqual(-100N / 2N, -50N) |
|||
Assert.AreEqual(g_zero / g_positive1, 0N) |
|||
() |
|||
|
|||
[<Test>] |
|||
member this.test_op_Equality() = |
|||
|
|||
Assert.IsTrue((g_positive1 = g_positive1)) |
|||
Assert.IsTrue((g_negative1 = g_negative1)) |
|||
Assert.IsTrue((g_zero = g_zero)) |
|||
Assert.IsTrue((g_normal = g_normal)) |
|||
() |
|||
|
|||
[<Test>] |
|||
member this.test_op_GreaterThan() = |
|||
Assert.AreEqual((g_positive1 > g_positive2), true) |
|||
Assert.AreEqual((g_negative1 > g_negative2), false) |
|||
Assert.AreEqual((g_zero > g_zero), false) |
|||
Assert.AreEqual((g_normal > g_normal), false) |
|||
|
|||
|
|||
() |
|||
[<Test>] |
|||
member this.test_op_GreaterThanOrEqual() = |
|||
Assert.AreEqual((g_positive1 >= g_positive2), true) |
|||
Assert.AreEqual((g_positive2 >= g_positive1), false) |
|||
Assert.AreEqual((g_negative1 >= g_negative1), true) |
|||
Assert.AreEqual((0N >= g_zero), true) |
|||
|
|||
() |
|||
[<Test>] |
|||
member this.test_op_LessThan() = |
|||
Assert.AreEqual((g_positive1 < g_positive2), false) |
|||
Assert.AreEqual((g_negative1 < g_negative3), false) |
|||
Assert.AreEqual((0N < g_zero), false) |
|||
|
|||
() |
|||
[<Test>] |
|||
member this.test_op_LessThanOrEqual() = |
|||
Assert.AreEqual((g_positive1 <= g_positive2), false) |
|||
Assert.AreEqual((g_positive2 <= g_positive1), true) |
|||
Assert.AreEqual((g_negative1 <= g_negative1), true) |
|||
Assert.AreEqual((0N <= g_zero), true) |
|||
|
|||
() |
|||
|
|||
[<Test>] |
|||
member this.test_op_Multiply() = |
|||
Assert.AreEqual(3N * 5N, 15N) |
|||
Assert.AreEqual((-3N) * (-5N), 15N) |
|||
Assert.AreEqual((-3N) * 5N, -15N) |
|||
Assert.AreEqual(0N * 5N, 0N) |
|||
|
|||
() |
|||
|
|||
[<Test>] |
|||
member this.test_op_Range() = |
|||
let resultPos = [0N .. 2N] |
|||
let seqPos = [0N; 1N; 2N] |
|||
verifySeqsEqual resultPos seqPos |
|||
|
|||
let resultNeg = [-2N .. 0N] |
|||
let seqNeg = [-2N; -1N; 0N] |
|||
verifySeqsEqual resultNeg seqNeg |
|||
|
|||
let resultSmall = [0N ..5N] |
|||
let seqSmall = [0N; 1N; 2N; 3N; 4N; 5N] |
|||
verifySeqsEqual resultSmall seqSmall |
|||
|
|||
() |
|||
|
|||
|
|||
[<Test>] |
|||
member this.test_op_RangeStep() = |
|||
let resultPos = [0N .. 3N .. 6N] |
|||
let seqPos = [0N; 3N; 6N] |
|||
verifySeqsEqual resultPos seqPos |
|||
|
|||
let resultNeg = [-6N .. 3N .. 0N] |
|||
let seqNeg = [-6N; -3N; 0N] |
|||
verifySeqsEqual resultNeg seqNeg |
|||
|
|||
let resultSmall = [0N .. 3N .. 9N] |
|||
let seqSmall = [0N; 3N; 6N; 9N] |
|||
verifySeqsEqual resultSmall seqSmall |
|||
|
|||
() |
|||
|
|||
[<Test>] |
|||
member this.test_op_Subtraction() = |
|||
Assert.AreEqual(g_positive1 - g_positive2,18N) |
|||
Assert.AreEqual(g_negative1 - g_negative3,18N) |
|||
Assert.AreEqual(0N-g_positive1, g_negative1) |
|||
() |
|||
|
|||
[<Test>] |
|||
member this.test_op_UnaryNegation() = |
|||
Assert.AreEqual(-g_positive1, g_negative1) |
|||
Assert.AreEqual(-g_negative1, g_positive1) |
|||
Assert.AreEqual(-0N,0N) |
|||
|
|||
() |
|||
|
|||
[<Test>] |
|||
member this.test_op_UnaryPlus() = |
|||
Assert.AreEqual(+g_positive1,g_positive1) |
|||
Assert.AreEqual(+g_negative1,g_negative1) |
|||
Assert.AreEqual(+0N, 0N) |
|||
|
|||
() |
|||
|
|||
// instance methods |
|||
[<Test>] |
|||
member this.Denominator() = |
|||
Assert.AreEqual(g_positive1.Denominator, 1I) |
|||
Assert.AreEqual(g_negative1.Denominator, 1I) |
|||
Assert.AreEqual(0N.Denominator, 1I) |
|||
|
|||
() |
|||
|
|||
[<Test>] |
|||
member this.IsNegative() = |
|||
Assert.IsFalse(g_positive1.IsNegative) |
|||
Assert.IsTrue(g_negative1.IsNegative) |
|||
|
|||
Assert.IsFalse( 0N.IsNegative) |
|||
Assert.IsFalse(-0N.IsNegative) |
|||
|
|||
() |
|||
|
|||
|
|||
[<Test>] |
|||
member this.IsPositive() = |
|||
|
|||
Assert.IsTrue(g_positive1.IsPositive) |
|||
Assert.IsFalse(g_negative1.IsPositive) |
|||
|
|||
Assert.IsFalse( 0N.IsPositive) |
|||
Assert.IsFalse(-0N.IsPositive) |
|||
|
|||
() |
|||
|
|||
[<Test>] |
|||
member this.Numerator() = |
|||
Assert.AreEqual(g_positive1.Numerator, g_bigintpositive) |
|||
Assert.AreEqual(g_negative1.Numerator, g_bigintnegative) |
|||
Assert.AreEqual(0N.Numerator, 0I) |
|||
|
|||
() |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
@ -0,0 +1,79 @@ |
|||
module MathNet.Numerics.Tests.DistributionTest |
|||
|
|||
open MathNet.Numerics |
|||
open MathNet.Numerics.Distribution |
|||
open NUnit.Framework |
|||
open FsUnit |
|||
|
|||
[<Test>] |
|||
let ``When creating a empty distribution, then the probability should be 1``() = |
|||
let actual = distribution { return () } |
|||
probability actual |> should equal (1N/1N) |
|||
|
|||
let sumOfTwoFairDices = distribution { |
|||
let! d1 = fairDice 6 |
|||
let! d2 = fairDice 6 |
|||
return d1 + d2 } |
|||
|
|||
[<Test>] |
|||
let ``When creating two fair dices, then P(Sum of 2 dices = 7) should be 1/6``() = |
|||
sumOfTwoFairDices |
|||
|> filter ((=) 7) |
|||
|> probability |
|||
|> should equal (1N/6N) |
|||
|
|||
let fairCoinAndDice = distribution { |
|||
let! d = fairDice 6 |
|||
let! c = fairCoin |
|||
return d,c } |
|||
|
|||
[<Test>] |
|||
let ``When creating a fair coin and a fair dice, then P(Heads) should be 1/2``() = |
|||
fairCoinAndDice |
|||
|> filter (fun (_,c) -> c = Heads) |
|||
|> probability |
|||
|> should equal (1N/2N) |
|||
|
|||
[<Test>] |
|||
let ``When creating a fair coin and a fair dice, then P(Heads and dice > 3) should be 1/4``() = |
|||
fairCoinAndDice |
|||
|> filter (fun (d,c) -> c = Heads && d > 3) |
|||
|> probability |
|||
|> should equal (1N/4N) |
|||
|
|||
// MontyHall Problem |
|||
// See Martin Erwig and Steve Kollmansberger's paper |
|||
// "Functional Pearls: Probabilistic functional programming in Haskell" |
|||
|
|||
type Outcome = |
|||
| Car |
|||
| Goat |
|||
|
|||
let firstChoice = toUniformDistribution [Car; Goat; Goat] |
|||
|
|||
let switch firstCoice = |
|||
match firstCoice with |
|||
| Car -> |
|||
// If you had the car and you switch ==> you lose since there are only goats left |
|||
certainly Goat |
|||
| Goat -> |
|||
// If you had the goat, the host has to take out another goat ==> you win |
|||
certainly Car |
|||
|
|||
[<Test>] |
|||
let ``When making the first choice in a MontyHall situation, the chances to win should be 1/3``() = |
|||
firstChoice |
|||
|> filter ((=) Car) |
|||
|> probability |
|||
|> should equal (1N/3N) |
|||
|
|||
let montyHallWithSwitch = distribution { |
|||
let! firstDoor = firstChoice |
|||
return! switch firstDoor } |
|||
|
|||
[<Test>] |
|||
let ``When switching in a MontyHall situation, the chances to win should be 2/3``() = |
|||
montyHallWithSwitch |
|||
|> filter ((=) Car) |
|||
|> probability |
|||
|> should equal (2N/3N) |
|||
@ -0,0 +1,96 @@ |
|||
module MathNet.Numerics.Tests.PokerDistributionTest |
|||
|
|||
open MathNet.Numerics |
|||
open MathNet.Numerics.Distribution |
|||
open NUnit.Framework |
|||
open FsUnit |
|||
|
|||
type Rank = int |
|||
type Suit = | Spades | Hearts | Diamonds | Clubs |
|||
type Card = Rank * Suit |
|||
|
|||
let value = fst |
|||
let suit = snd |
|||
|
|||
let A,K,Q,J,T = 14,13,12,11,10 |
|||
let allRanksInSuit suit = [2..A] |> List.map (fun rank -> rank,suit) |
|||
let completeDeck = |
|||
[Spades; Hearts ; Diamonds; Clubs] |
|||
|> List.map allRanksInSuit |
|||
|> List.concat |
|||
|
|||
let isPair c1 c2 = value c1 = value c2 |
|||
let isSuited c1 c2 = suit c1 = suit c2 |
|||
let isConnected c1 c2 = |
|||
let v1,v2 = value c1,value c2 |
|||
(v1 - v2 |> abs |> (=) 1) || |
|||
(v1 = A && v2 = 2) || |
|||
(v1 = 2 && v2 = A) |
|||
|
|||
[<Test>] |
|||
let ``When drawing from a full deck, then the probability for an Ace should equal 4/52``() = |
|||
completeDeck |
|||
|> selectOne |> map fst |
|||
|> filter (fun card -> value card = A) |
|||
|> probability |
|||
|> should equal (4N/52N) |
|||
|
|||
[<Test>] |
|||
let ``When drawing from a full deck, then the probability should equal 1/52``() = |
|||
completeDeck |
|||
|> selectOne |> map fst |
|||
|> filter ((=) (A,Spades)) |
|||
|> probability |
|||
|> should equal (1N/52N) |
|||
|
|||
[<Test>] |
|||
let ``When drawing from a full deck, then the probability for the Ace of Clubs and Ace of Spaces (in order) should equal 1/52 * 1/51``() = |
|||
completeDeck |
|||
|> select 2 |
|||
|> filter ((=) [A,Clubs; A,Spades]) |
|||
|> probability |
|||
|> should equal (1N/52N * 1N/51N) |
|||
|
|||
[<Test>] |
|||
let ``When drawing from a full deck, then the probability for the Ace of Clubs and Ace of Spaces (in any order) should equal (1/52 * 1/51) * 2``() = |
|||
completeDeck |
|||
|> select 2 |
|||
|> filterInAnyOrder [A,Clubs; A,Spades] |
|||
|> probability |
|||
|> should equal ((1N/52N * 1N/51N) * 2N) |
|||
|
|||
[<Test>] |
|||
let ``When drawing the Ace of Spades and the Ace of Clubs, then the probability for drawing another Ace should equal 2/50``() = |
|||
completeDeck |
|||
|> remove [A,Clubs; A,Spades] |
|||
|> toUniformDistribution |
|||
|> filter (fun card -> value card = A) |
|||
|> probability |
|||
|> should equal (2N/50N) |
|||
|
|||
|
|||
[<Test>] |
|||
let ``When drawing from the full deck, then the probability for drawing a Pair preflop should equal 1/17``() = |
|||
completeDeck |
|||
|> select 2 |
|||
|> filter (fun (c1::c2::_) -> isPair c1 c2) |
|||
|> probability |
|||
|> should equal (1N/17N) |
|||
|
|||
[<Test>] |
|||
let ``When drawing from the full deck, then the probability for drawing Suited Connectors should equal 1/25``() = |
|||
completeDeck |
|||
|> select 2 |
|||
|> filter (fun (c1::c2::_) -> isSuited c1 c2 && isConnected c1 c2) |
|||
|> probability |
|||
|> should equal (2N/51N) |
|||
|
|||
[<Test>] |
|||
let ``When holding 3 Spades after the flop, than the probability for drawing a flush should equal 10/47*9/46``() = |
|||
completeDeck |
|||
|> remove [A,Clubs; A,Spades] // preflop |
|||
|> remove [2,Clubs; 3,Spades; 7,Spades] // flop |
|||
|> select 2 |
|||
|> filter (fun (c1::c2::_) -> suit c1 = Spades && suit c2 = Spades) |
|||
|> probability |
|||
|> should equal (10N/47N*9N/46N) |
|||
@ -0,0 +1,128 @@ |
|||
// First version copied from the F# Power Pack |
|||
// https://raw.github.com/fsharp/powerpack/master/src/FSharp.PowerPack.Unittests/Utilities.fs |
|||
|
|||
namespace MathNet.Numerics.Tests |
|||
open NUnit.Framework |
|||
open System |
|||
open System.Collections.Generic |
|||
|
|||
[<AutoOpen>] |
|||
module Utilities = |
|||
let test msg b = Assert.IsTrue(b, "MiniTest '" + msg + "'") |
|||
let logMessage msg = |
|||
System.Console.WriteLine("LOG:" + msg) |
|||
// System.Diagnostics.Trace.WriteLine("LOG:" + msg) |
|||
let check msg v1 v2 = test msg (v1 = v2) |
|||
let reportFailure msg = Assert.Fail msg |
|||
let numActiveEnumerators = ref 0 |
|||
let throws f = try f() |> ignore; false with e -> true |
|||
|
|||
let countEnumeratorsAndCheckedDisposedAtMostOnceAtEnd (seq: seq<'a>) = |
|||
let enumerator() = |
|||
numActiveEnumerators := !numActiveEnumerators + 1; |
|||
let disposed = ref false in |
|||
let endReached = ref false in |
|||
let ie = seq.GetEnumerator() in |
|||
{ new System.Collections.Generic.IEnumerator<'a> with |
|||
member x.Current = |
|||
test "rvlrve0" (not !endReached); |
|||
test "rvlrve1" (not !disposed); |
|||
ie.Current |
|||
member x.Dispose() = |
|||
test "rvlrve2" !endReached; |
|||
test "rvlrve4" (not !disposed); |
|||
numActiveEnumerators := !numActiveEnumerators - 1; |
|||
disposed := true; |
|||
ie.Dispose() |
|||
interface System.Collections.IEnumerator with |
|||
member x.MoveNext() = |
|||
test "rvlrve0" (not !endReached); |
|||
test "rvlrve3" (not !disposed); |
|||
endReached := not (ie.MoveNext()); |
|||
not !endReached |
|||
member x.Current = |
|||
test "qrvlrve0" (not !endReached); |
|||
test "qrvlrve1" (not !disposed); |
|||
box ie.Current |
|||
member x.Reset() = |
|||
ie.Reset() |
|||
} in |
|||
|
|||
{ new seq<'a> with |
|||
member x.GetEnumerator() = enumerator() |
|||
interface System.Collections.IEnumerable with |
|||
member x.GetEnumerator() = (enumerator() :> _) } |
|||
|
|||
let countEnumeratorsAndCheckedDisposedAtMostOnce (seq: seq<'a>) = |
|||
let enumerator() = |
|||
let disposed = ref false in |
|||
let endReached = ref false in |
|||
let ie = seq.GetEnumerator() in |
|||
numActiveEnumerators := !numActiveEnumerators + 1; |
|||
{ new System.Collections.Generic.IEnumerator<'a> with |
|||
member x.Current = |
|||
test "qrvlrve0" (not !endReached); |
|||
test "qrvlrve1" (not !disposed); |
|||
ie.Current |
|||
member x.Dispose() = |
|||
test "qrvlrve4" (not !disposed); |
|||
numActiveEnumerators := !numActiveEnumerators - 1; |
|||
disposed := true; |
|||
ie.Dispose() |
|||
interface System.Collections.IEnumerator with |
|||
member x.MoveNext() = |
|||
test "qrvlrve0" (not !endReached); |
|||
test "qrvlrve3" (not !disposed); |
|||
endReached := not (ie.MoveNext()); |
|||
not !endReached |
|||
member x.Current = |
|||
test "qrvlrve0" (not !endReached); |
|||
test "qrvlrve1" (not !disposed); |
|||
box ie.Current |
|||
member x.Reset() = |
|||
ie.Reset() |
|||
} in |
|||
|
|||
{ new seq<'a> with |
|||
member x.GetEnumerator() = enumerator() |
|||
interface System.Collections.IEnumerable with |
|||
member x.GetEnumerator() = (enumerator() :> _) } |
|||
|
|||
// Verifies two sequences are equal (same length, equiv elements) |
|||
let verifySeqsEqual seq1 seq2 = |
|||
if Seq.length seq1 <> Seq.length seq2 then Assert.Fail() |
|||
|
|||
let zippedElements = Seq.zip seq1 seq2 |
|||
if zippedElements |> Seq.forall (fun (a, b) -> a = b) |
|||
then () |
|||
else Assert.Fail() |
|||
|
|||
/// Check that the lamda throws an exception of the given type. Otherwise |
|||
/// calls Assert.Fail() |
|||
let private checkThrowsExn<'a when 'a :> exn> (f : unit -> unit) = |
|||
let funcThrowsAsExpected = |
|||
try |
|||
let _ = f () |
|||
false // Did not throw! |
|||
with |
|||
| :? 'a |
|||
-> true // Thew null ref, OK |
|||
| _ -> false // Did now throw a null ref exception! |
|||
if funcThrowsAsExpected |
|||
then () |
|||
else Assert.Fail() |
|||
|
|||
// Illegitimate exceptions. Once we've scrubbed the library, we should add an |
|||
// attribute to flag these exception's usage as a bug. |
|||
let checkThrowsNullRefException f = checkThrowsExn<NullReferenceException> f |
|||
let checkThrowsIndexOutRangException f = checkThrowsExn<IndexOutOfRangeException> f |
|||
|
|||
// Legit exceptions |
|||
let checkThrowsNotSupportedException f = checkThrowsExn<NotSupportedException> f |
|||
let checkThrowsArgumentException f = checkThrowsExn<ArgumentException> f |
|||
let checkThrowsArgumentNullException f = checkThrowsExn<ArgumentNullException> f |
|||
let checkThrowsKeyNotFoundException f = checkThrowsExn<KeyNotFoundException> f |
|||
let checkThrowsDivideByZeroException f = checkThrowsExn<DivideByZeroException> f |
|||
let checkThrowsInvalidOperationExn f = checkThrowsExn<InvalidOperationException> f |
|||
|
|||
|
|||
@ -0,0 +1,4 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<packages> |
|||
<package id="NUnit" version="2.6.2" targetFramework="net40" /> |
|||
</packages> |
|||
Loading…
Reference in new issue