Math.NET Numerics
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

374 lines
16 KiB

// (c) Microsoft Corporation. All rights reserved
#nowarn "44" // OK to use the "compiler only" function RangeGeneric
namespace Microsoft.FSharp.Math
open Microsoft.FSharp.Collections
open Microsoft.FSharp.Core
open Microsoft.FSharp.Math
open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
open Microsoft.FSharp.Primitives.Basics
open Microsoft.FSharp.Core.Operators
open System
open System.Globalization
module BigRationalLargeImpl =
let ZeroI = new BigInt(0)
let OneI = new BigInt(1)
let bigint (x:int) = new BigInt(x)
let ToDoubleI (x:bigint) =
#if FX_ATLEAST_40
(BigInt.op_Explicit x : double)
#else
BigInt.ToDouble x
#endif
let ToInt32I x =
#if FX_ATLEAST_40
(BigInt.op_Explicit x : int32)
#else
BigInt.ToInt32 x
#endif
open BigRationalLargeImpl
[<StructuralEquality(false); StructuralComparison(false)>]
type BigRationalLarge =
| Q of BigInt * BigInt // 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) as q) =
// This hash code must be identical to the hash for BigInt 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)) =
BigInt.(=) (ap,bp) && BigInt.(=) (aq,bq) // normal form, so structural equality
static member LessThan(Q(ap,aq), Q(bp,bq)) =
BigInt.(<) (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,aq)) = x in sign ap < 0
member x.IsPositive = let (Q(ap,aq)) = x in sign ap > 0
member x.Numerator = let (Q(p,q)) = x in p
member x.Denominator = let (Q(p,q)) = x in q
member x.Sign = (let (Q(p,q)) = x in sign p)
static member ToDouble (Q(p,q)) =
ToDoubleI p / ToDoubleI q
static member Normalize (p:BigInt,q:BigInt) =
if q.IsZero then
raise (System.DivideByZeroException()) (* throw for any x/0 *)
elif q.IsOne then
Q(p,q)
else
#if FX_ATLEAST_40
let k = BigInt.GreatestCommonDivisor(p,q)
#else
let k = BigInt.Gcd(p,q)
#endif
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 = BigInt.Parse (str.Substring(0,j))
let q = BigInt.Parse (str.Substring(j+1,len-j-1))
BigRationalLarge.RationalZ (p,q)
else
let p = BigInt.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
(*
static member Floor (Q(p,q)) =
let d,r = BigInt.DivRem (p,q) // p = d.q + r
if sign r < 0
then d - OneI // r -ve, so round down
else d
static member Ceiling (Q(p,q)) =
let d,r = BigInt.DivRem (p,q) // p = d.q + r
if sign r > 0
then d + OneI // when r +ve, adjust up
else d
*)
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module BigRationalLarge =
let inv (Q(ap,aq)) = BigRationalLarge.Normalize(aq,ap)
#if FX_ATLEAST_40
let pown (Q(p,q)) (n:int) = Q(BigInt.Pow(p,n),BigInt.Pow (q,n))
#else
let pow (Q(p,q)) (z:bigint) = Q(BigInt.Pow(p,z),BigInt.Pow (q,z)) // p,q powers still coprime
let powi q (n:int) = let z = bigint n in pow q z
#endif
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)) = BigInt.(<=) (ap * bq,bp * aq)
let gte (Q(ap,aq)) (Q(bp,bq)) = BigInt.(>=) (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 d,r = BigInt.DivRem (p,q) // 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
(*
let two = BigInt 2
let round (Q(p,q)) =
let d,r = BigInt.DivRem (p,q) // have p = d.q + r for |r|<q
let s = sign r
if s > 0 then
if BigInt.(<) (q / two,r)
then OneI + d // have q/2 < r < q , round up
else d // have 0 < r <= q/2, note 1/2 rounds down
elif s < 0 then
if BigInt.(<=) (q / two, -r)
then OneI - d // have -1 < r <= q/2 , round down. note 1/2 rounds down again
else d // have -q/2 < r < 0 , rounds up
else d // have r=0
*)
//----------------------------------------------------------------------------
// BigNum
//--------------------------------------------------------------------------
[<StructuralEquality(false); StructuralComparison(false)>]
[<StructuredFormatDisplay("{StructuredDisplayString}N")>]
type BigNum =
| Z of BigInt
| 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:BigNum) = 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
| :? BigNum as that -> BigNum.(=)(this, that)
| _ -> false
interface System.IComparable with
member n1.CompareTo(obj:obj) =
match obj with
| :? BigNum as n2 ->
if BigNum.(<)(n1, n2) then -1 elif BigNum.(=)(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 = BigNum.FromInt(0)
static member One = BigNum.FromInt(1)
static member PowN (n,i:int) =
match n with
#if FX_ATLEAST_40
| Z z -> Z (BigInt.Pow (z,i))
| Q q -> Q (BigRationalLarge.pown q i)
#else
| Z z -> Z (BigInt.Pow (z,bigint i))
| Q q -> Q (BigRationalLarge.powi q i)
#endif
static member op_Equality (n,nn) =
match n,nn with
| Z z ,Z zz -> BigInt.(=) (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 (BigNum.op_Equality(n,nn))
static member op_LessThan (n,nn) =
match n,nn with
| Z z ,Z zz -> BigInt.(<) (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 -> BigInt.(>) (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 -> BigInt.(<=) (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 -> BigInt.(>=) (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 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:BigNum) =
if n.IsNegative then -n else n
static member ToDouble(n:BigNum) =
match n with
| Z z -> ToDoubleI z
| Q q -> BigRationalLarge.ToDouble q
static member ToBigInt(n:BigNum) =
match n with
| Z z -> z
| Q q -> BigRationalLarge.integer q
static member ToInt32(n:BigNum) =
match n with
| Z z -> ToInt32I(z)
| Q q -> ToInt32I(BigRationalLarge.integer q )
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 BigRational = BigNum
type bignum = BigNum
namespace Microsoft.FSharp.Core
open Microsoft.FSharp.Math
type bignum = BigNum
// FxCop suppressions
open System.Diagnostics.CodeAnalysis
[<assembly: SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Scope="member", Target="Microsoft.FSharp.Math.BigNum.#op_Addition(Microsoft.FSharp.Math.BigNum,Microsoft.FSharp.Math.BigNum)")>]
[<assembly: SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Scope="member", Target="Microsoft.FSharp.Math.BigNum.#op_Division(Microsoft.FSharp.Math.BigNum,Microsoft.FSharp.Math.BigNum)")>]
[<assembly: SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Scope="member", Target="Microsoft.FSharp.Math.BigNum.#op_GreaterThan(Microsoft.FSharp.Math.BigNum,Microsoft.FSharp.Math.BigNum)")>]
[<assembly: SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Scope="member", Target="Microsoft.FSharp.Math.BigNum.#op_GreaterThanOrEqual(Microsoft.FSharp.Math.BigNum,Microsoft.FSharp.Math.BigNum)")>]
[<assembly: SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Scope="member", Target="Microsoft.FSharp.Math.BigNum.#op_LessThan(Microsoft.FSharp.Math.BigNum,Microsoft.FSharp.Math.BigNum)")>]
[<assembly: SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Scope="member", Target="Microsoft.FSharp.Math.BigNum.#op_LessThanOrEqual(Microsoft.FSharp.Math.BigNum,Microsoft.FSharp.Math.BigNum)")>]
[<assembly: SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Scope="member", Target="Microsoft.FSharp.Math.BigNum.#op_Multiply(Microsoft.FSharp.Math.BigNum,Microsoft.FSharp.Math.BigNum)")>]
[<assembly: SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Scope="member", Target="Microsoft.FSharp.Math.BigNum.#op_Subtraction(Microsoft.FSharp.Math.BigNum,Microsoft.FSharp.Math.BigNum)")>]
[<assembly: SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Scope="member", Target="Microsoft.FSharp.Math.BigNum.#op_UnaryNegation(Microsoft.FSharp.Math.BigNum)")>]
[<assembly: SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Scope="member", Target="Microsoft.FSharp.Math.BigNum.#op_UnaryPlus(Microsoft.FSharp.Math.BigNum)")>]
do()
module NumericLiteralN =
let FromZero () = BigNum.Zero
let FromOne () = BigNum.One
let FromInt32 i = BigNum.FromInt i
let FromInt64 (i64:int64) = BigNum.FromBigInt (new BigInt(i64))
let FromString s = BigNum.Parse s