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.
 
 
 

818 lines
44 KiB

//=========================================================================
// (c) Microsoft Corporation 2005-2009.
//=========================================================================
namespace Microsoft.FSharp.Collections
open Microsoft.FSharp.Core
open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
open Microsoft.FSharp.Core.Operators
open Microsoft.FSharp.Collections
open System.Collections
open System.Collections.Generic
open System.Diagnostics
(* A classic functional language implementation of binary trees *)
[<CompilationRepresentation(CompilationRepresentationFlags.UseNullAsTrueValue)>]
type (* internal *) SetTree<'T> =
| SetEmpty // height = 0
| SetNode of 'T * SetTree<'T> * SetTree<'T> * int // height = int
| SetOne of 'T // height = 1
// OPTIMIZATION: store SetNode(k,SetEmpty,SetEmpty,1) ---> SetOne(k)
// REVIEW: performance rumour has it that the data held in SetNode and SetOne should be
// exactly one cache line on typical architectures. They are currently
// ~6 and 3 words respectively.
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module internal SetTree =
let height t =
match t with
| SetEmpty -> 0
| SetOne _ -> 1
| SetNode (_,_,_,h) -> h
#if CHECKED
let rec checkInvariant t =
// A good sanity check, loss of balance can hit perf
match t with
| SetEmpty -> true
| SetOne _ -> true
| SetNode (k,t1,t2,h) ->
let h1 = height t1
let h2 = height t2
(-2 <= (h1 - h2) && (h1 - h2) <= 2) && checkInvariant t1 && checkInvariant t2
#endif
let tolerance = 2
let mk l k r =
match l,r with
| SetEmpty,SetEmpty -> SetOne (k)
| _ ->
let hl = height l
let hr = height r
let m = if hl < hr then hr else hl
SetNode(k,l,r,m+1)
let rebalance t1 k t2 =
let t1h = height t1
let t2h = height t2
if t2h > t1h + tolerance then // right is heavier than left
match t2 with
| SetNode(t2k,t2l,t2r,t2h) ->
// one of the nodes must have height > height t1 + 1
if height t2l > t1h + 1 then // balance left: combination
match t2l with
| SetNode(t2lk,t2ll,t2lr,t2lh) ->
mk (mk t1 k t2ll) t2lk (mk t2lr t2k t2r)
| _ -> failwith "rebalance"
else // rotate left
mk (mk t1 k t2l) t2k t2r
| _ -> failwith "rebalance"
else
if t1h > t2h + tolerance then // left is heavier than right
match t1 with
| SetNode(t1k,t1l,t1r,t1h) ->
// one of the nodes must have height > height t2 + 1
if height t1r > t2h + 1 then
// balance right: combination
match t1r with
| SetNode(t1rk,t1rl,t1rr,t1rh) ->
mk (mk t1l t1k t1rl) t1rk (mk t1rr k t2)
| _ -> failwith "rebalance"
else
mk t1l t1k (mk t1r k t2)
| _ -> failwith "rebalance"
else mk t1 k t2
let rec add (comparer: OptimizedClosures.FastFunc2<'T,'T,int>) k t =
match t with
| SetNode (k2,l,r,h) ->
let c = comparer.Invoke(k,k2)
if c < 0 then rebalance (add comparer k l) k2 r
elif c = 0 then t
else rebalance l k2 (add comparer k r)
| SetOne(k2) ->
// nb. no check for rebalance needed for small trees, also be sure to reuse node already allocated
let c = comparer.Invoke(k,k2)
if c < 0 then SetNode (k,SetEmpty,t,2)
elif c = 0 then t
else SetNode (k,t,SetEmpty,2)
| SetEmpty -> SetOne(k)
let rec balance comparer t1 k t2 =
// Given t1 < k < t2 where t1 and t2 are "balanced",
// return a balanced tree for <t1,k,t2>.
// Recall: balance means subtrees heights differ by at most "tolerance"
match t1,t2 with
| SetEmpty,t2 -> add comparer k t2 // drop t1 = empty
| t1,SetEmpty -> add comparer k t1 // drop t2 = empty
| SetOne k1,t2 -> add comparer k (add comparer k1 t2)
| t1,SetOne k2 -> add comparer k (add comparer k2 t1)
| SetNode(k1,t11,t12,h1),SetNode(k2,t21,t22,h2) ->
// Have: (t11 < k1 < t12) < k < (t21 < k2 < t22)
// Either (a) h1,h2 differ by at most 2 - no rebalance needed.
// (b) h1 too small, i.e. h1+2 < h2
// (c) h2 too small, i.e. h2+2 < h1
if h1+tolerance < h2 then
// case: b, h1 too small
// push t1 into low side of t2, may increase height by 1 so rebalance
rebalance (balance comparer t1 k t21) k2 t22
elif h2+tolerance < h1 then
// case: c, h2 too small
// push t2 into high side of t1, may increase height by 1 so rebalance
rebalance t11 k1 (balance comparer t12 k t2)
else
// case: a, h1 and h2 meet balance requirement
mk t1 k t2
let rec split (comparer : OptimizedClosures.FastFunc2<'T,'T,int>) pivot t =
// Given a pivot and a set t
// Return { x in t s.t. x < pivot }, pivot in t? , { x in t s.t. x > pivot }
match t with
| SetNode(k1,t11,t12,h1) ->
let c = comparer.Invoke(pivot,k1)
if c < 0 then // pivot t1
let t11_lo,havePivot,t11_hi = split comparer pivot t11
t11_lo,havePivot,balance comparer t11_hi k1 t12
elif c = 0 then // pivot is k1
t11,true,t12
else // pivot t2
let t12_lo,havePivot,t12_hi = split comparer pivot t12
balance comparer t11 k1 t12_lo,havePivot,t12_hi
| SetOne k1 ->
let c = comparer.Invoke(k1,pivot)
if c < 0 then t ,false,SetEmpty // singleton under pivot
elif c = 0 then SetEmpty,true ,SetEmpty // singleton is pivot
else SetEmpty,false,t // singleton over pivot
| SetEmpty ->
SetEmpty,false,SetEmpty
let rec spliceOutSuccessor t =
match t with
| SetEmpty -> failwith "internal error: Map.splice_out_succ_or_pred"
| SetOne (k2) -> k2,SetEmpty
| SetNode (k2,l,r,_) ->
match l with
| SetEmpty -> k2,r
| _ -> let k3,l' = spliceOutSuccessor l in k3,mk l' k2 r
let rec remove (comparer: OptimizedClosures.FastFunc2<'T,'T,int>) k t =
match t with
| SetEmpty -> t
| SetOne (k2) ->
let c = comparer.Invoke(k,k2)
if c = 0 then SetEmpty
else t
| SetNode (k2,l,r,_) ->
let c = comparer.Invoke(k,k2)
if c < 0 then rebalance (remove comparer k l) k2 r
elif c = 0 then
match l,r with
| SetEmpty,_ -> r
| _,SetEmpty -> l
| _ ->
let sk,r' = spliceOutSuccessor r
mk l sk r'
else rebalance l k2 (remove comparer k r)
let rec mem (comparer: OptimizedClosures.FastFunc2<'T,'T,int>) k t =
match t with
| SetNode(k2,l,r,_) ->
let c = comparer.Invoke(k,k2)
if c < 0 then mem comparer k l
elif c = 0 then true
else mem comparer k r
| SetOne(k2) -> (comparer.Invoke(k,k2) = 0)
| SetEmpty -> false
let rec iter f t =
match t with
| SetNode(k2,l,r,_) -> iter f l; f k2; iter f r
| SetOne(k2) -> f k2
| SetEmpty -> ()
let rec fold_right f m x =
match m with
| SetNode(k,l,r,h) -> fold_right f l (f k (fold_right f r x))
| SetOne(k) -> f k x
| SetEmpty -> x
let rec fold_left f x m =
match m with
| SetNode(k,l,r,h) ->
let x = fold_left f x l in
let x = f x k
fold_left f x r
| SetOne(k) -> f x k
| SetEmpty -> x
let rec for_all f m =
match m with
| SetNode(k2,l,r,h) -> f k2 && for_all f l && for_all f r
| SetOne(k2) -> f k2
| SetEmpty -> true
let rec exists f m =
match m with
| SetNode(k2,l,r,h) -> f k2 || exists f l || exists f r
| SetOne(k2) -> f k2
| SetEmpty -> false
let is_empty m = match m with | SetEmpty -> true | _ -> false
let subset comparer a b = for_all (fun x -> mem comparer x b) a
let rec filterAux comparer f s acc =
match s with
| SetNode(k,l,r,_) ->
let acc = if f k then add comparer k acc else acc
filterAux comparer f l (filterAux comparer f r acc)
| SetOne(k) -> if f k then add comparer k acc else acc
| SetEmpty -> acc
let filter comparer f s = filterAux comparer f s SetEmpty
let rec diffAux comparer m acc =
match m with
| SetNode(k,l,r,_) -> diffAux comparer l (diffAux comparer r (remove comparer k acc))
| SetOne(k) -> remove comparer k acc
| SetEmpty -> acc
let diff comparer a b = diffAux comparer b a
let rec countAux s acc =
match s with
| SetNode(k,l,r,_) -> countAux l (countAux r (acc+1))
| SetOne(k) -> acc+1
| SetEmpty -> acc
let count s = countAux s 0
let rec union comparer t1 t2 =
// Perf: tried bruteForce for low heights, but nothing significant
match t1,t2 with
| SetNode(k1,t11,t12,h1),SetNode(k2,t21,t22,h2) -> // (t11 < k < t12) AND (t21 < k2 < t22)
// Divide and Quonquer:
// Suppose t1 is largest.
// Split t2 using pivot k1 into lo and hi.
// Union disjoint subproblems and then combine.
if h1 > h2 then
let lo,_,hi = split comparer k1 t2 in
balance comparer (union comparer t11 lo) k1 (union comparer t12 hi)
else
let lo,_,hi = split comparer k2 t1 in
balance comparer (union comparer t21 lo) k2 (union comparer t22 hi)
| SetEmpty,t -> t
| t,SetEmpty -> t
| SetOne k1,t2 -> add comparer k1 t2
| t1,SetOne k2 -> add comparer k2 t1
let rec intersectionAux comparer b m acc =
match m with
| SetNode(k,l,r,_) ->
let acc = intersectionAux comparer b r acc
let acc = if mem comparer k b then add comparer k acc else acc
intersectionAux comparer b l acc
| SetOne(k) ->
if mem comparer k b then add comparer k acc else acc
| SetEmpty -> acc
let intersection comparer a b = intersectionAux comparer b a SetEmpty
let partition1 comparer f k (acc1,acc2) = if f k then (add comparer k acc1,acc2) else (acc1,add comparer k acc2)
let rec partitionAux comparer f s acc =
match s with
| SetNode(k,l,r,_) ->
let acc = partitionAux comparer f r acc
let acc = partition1 comparer f k acc
partitionAux comparer f l acc
| SetOne(k) -> partition1 comparer f k acc
| SetEmpty -> acc
let partition comparer f s = partitionAux comparer f s (SetEmpty,SetEmpty)
// It's easier to get many less-important algorithms right using this active pattern
let (|MatchSetNode|MatchSetEmpty|) s =
match s with
| SetNode(k2,l,r,_) -> MatchSetNode(k2,l,r)
| SetOne(k2) -> MatchSetNode(k2,SetEmpty,SetEmpty)
| SetEmpty -> MatchSetEmpty
let rec nextElemCont (comparer: OptimizedClosures.FastFunc2<'T,'T,int>) k s cont =
match s with
| MatchSetNode(k2,l,r) ->
let c = comparer.Invoke(k,k2)
if c < 0 then nextElemCont comparer k l (function None -> cont(Some(k2)) | res -> res)
elif c = 0 then cont(minimumElementOpt r)
else nextElemCont comparer k r cont
| MatchSetEmpty -> cont(None)
and nextElem comparer k s = nextElemCont comparer k s (fun res -> res)
and prevElemCont (comparer: OptimizedClosures.FastFunc2<'T,'T,int>) k s cont =
match s with
| MatchSetNode(k2,l,r) ->
let c = comparer.Invoke(k,k2)
if c > 0 then prevElemCont comparer k r (function None -> cont(Some(k2)) | res -> res)
elif c = 0 then cont(maximumElementOpt r)
else prevElemCont comparer k l cont
| MatchSetEmpty -> cont(None)
and prevElem comparer k s = prevElemCont comparer k s (fun res -> res)
and minimumElementAux s n =
match s with
| SetNode(k,l,r,_) -> minimumElementAux l k
| SetOne(k) -> k
| SetEmpty -> n
and minimumElementOpt s =
match s with
| SetNode(k,l,r,_) -> Some(minimumElementAux l k)
| SetOne(k) -> Some k
| SetEmpty -> None
and maximumElementAux s n =
match s with
| SetNode(k,l,r,_) -> maximumElementAux r k
| SetOne(k) -> k
| SetEmpty -> n
and maximumElementOpt s =
match s with
| SetNode(k,l,r,_) -> Some(maximumElementAux r k)
| SetOne(k) -> Some(k)
| SetEmpty -> None
let minimumElement s =
match minimumElementOpt s with
| Some(k) -> k
| None -> failwith "minimumElement"
let maximumElement s =
match maximumElementOpt s with
| Some(k) -> k
| None -> failwith "maximumElement"
//--------------------------------------------------------------------------
// Imperative left-to-right iterators.
//--------------------------------------------------------------------------
[<StructuralEquality(false); StructuralComparison(false)>]
type iterator<'T> =
{ mutable stack: SetTree<'T> list; // invariant: always collapseLHS result
mutable started : bool // true when MoveNext has been called
}
// collapseLHS:
// a) Always returns either [] or a list starting with SetOne.
// b) The "fringe" of the set stack is unchanged.
let rec collapseLHS stack =
match stack with
| [] -> []
| SetEmpty :: rest -> collapseLHS rest
| SetOne k :: rest -> stack
| SetNode(k,l,r,h) :: rest -> collapseLHS (l :: SetOne k :: r :: rest)
let mkIterator s = { stack = collapseLHS [s]; started = false }
let not_started() = raise (new System.InvalidOperationException("Enumeration has not started. Call MoveNext."))
let already_finished() = raise (new System.InvalidOperationException("Enumeration already finished."))
let current i =
if i.started then
match i.stack with
| SetOne k :: _ -> k
| [] -> already_finished()
| _ -> failwith "Please report error: Set iterator, unexpected stack for current"
else
not_started()
let rec moveNext i =
if i.started then
match i.stack with
| SetOne k :: rest -> ( i.stack <- collapseLHS rest;
i.stack <> []
)
| [] -> false
| _ -> failwith "Please report error: Set iterator, unexpected stack for moveNext"
else
i.started <- true; // The first call to MoveNext "starts" the enumeration.
i.stack <> []
let mkIEnumerator s =
let i = ref (mkIterator s)
{ new IEnumerator<_> with
member x.Current = current !i
interface IEnumerator with
member x.Current = box (current !i)
member x.MoveNext() = moveNext !i
member x.Reset() = i := mkIterator s
interface System.IDisposable with
member x.Dispose() = () }
//--------------------------------------------------------------------------
// Set comparison. This can be expensive.
//--------------------------------------------------------------------------
let rec compareStacks (comparer: OptimizedClosures.FastFunc2<'T,'T,int>) l1 l2 =
match l1,l2 with
| [],[] -> 0
| [],_ -> -1
| _ ,[] -> 1
| (SetEmpty _ :: t1),(SetEmpty :: t2) -> compareStacks comparer t1 t2
| (SetOne(n1k) :: t1),(SetOne(n2k) :: t2) ->
let c = comparer.Invoke(n1k,n2k)
if c <> 0 then c else compareStacks comparer t1 t2
| (SetOne(n1k) :: t1),(SetNode(n2k,SetEmpty,n2r,_) :: t2) ->
let c = comparer.Invoke(n1k,n2k)
if c <> 0 then c else compareStacks comparer (SetEmpty :: t1) (n2r :: t2)
| (SetNode(n1k,(SetEmpty as emp),n1r,_) :: t1),(SetOne(n2k) :: t2) ->
let c = comparer.Invoke(n1k,n2k)
if c <> 0 then c else compareStacks comparer (n1r :: t1) (emp :: t2)
| (SetNode(n1k,(SetEmpty as emp),n1r,_) :: t1),(SetNode(n2k,SetEmpty,n2r,_) :: t2) ->
let c = comparer.Invoke(n1k,n2k)
if c <> 0 then c else compareStacks comparer (n1r :: t1) (n2r :: t2)
| (SetOne(n1k) :: t1),_ ->
compareStacks comparer (SetEmpty :: SetOne(n1k) :: t1) l2
| (SetNode(n1k,n1l,n1r,_) :: t1),_ ->
compareStacks comparer (n1l :: SetNode(n1k,SetEmpty,n1r,0) :: t1) l2
| _,(SetOne(n2k) :: t2) ->
compareStacks comparer l1 (SetEmpty :: SetOne(n2k) :: t2)
| _,(SetNode(n2k,n2l,n2r,_) :: t2) ->
compareStacks comparer l1 (n2l :: SetNode(n2k,SetEmpty,n2r,0) :: t2)
let compare comparer s1 s2 =
match s1,s2 with
| SetEmpty,SetEmpty -> 0
| SetEmpty,_ -> -1
| _,SetEmpty -> 1
| _ -> compareStacks comparer [s1] [s2]
let choose s = minimumElement s
let to_list s =
let rec loop m acc =
match m with
| SetNode(k,l,r,h) -> loop l (k :: loop r acc)
| SetOne(k) -> k ::acc
| SetEmpty -> acc
loop s []
let copyToArray s (arr: _[]) i =
let j = ref i
iter (fun x -> arr.[!j] <- x; j := !j + 1) s
let to_array s =
let n = (count s)
let res = Array.zeroCreate n
copyToArray s res 0;
res
let rec mkFromEnumerator comparer acc (e : IEnumerator<_>) =
if e.MoveNext() then
mkFromEnumerator comparer (add comparer e.Current acc) e
else acc
let of_seq comparer (c : IEnumerable<_>) =
use ie = c.GetEnumerator()
mkFromEnumerator comparer SetEmpty ie
let of_array comparer l = Array.fold (fun acc k -> add comparer k acc) SetEmpty l
[<Sealed>]
#if FX_NO_DEBUG_PROXIES
#else
[<System.Diagnostics.DebuggerTypeProxy(typedefof<SetDebugView<_>>)>]
#endif
#if FX_NO_DEBUG_DISPLAYS
#else
[<System.Diagnostics.DebuggerDisplay("Count = {Count}")>]
#endif
[<CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")>]
[<CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId="Set")>]
type Set<'T>(comparer:OptimizedClosures.FastFunc2<'T,'T,int>, tree: SetTree<'T>) =
// We use .NET generics per-instantiation static fields to avoid allocating a new object for each empty
// set (it is just be a lookup into a .NET table of type-instantiation-indexed static fields).
static let empty : Set<'T> =
let comparer = ComparisonIdentity.GetFastStructuralComparisonFunction<'T>()
new Set<'T>(comparer,SetEmpty)
#if FX_NO_DEBUG_DISPLAYS
#else
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
#endif
member internal set.Comparer = comparer
//[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member internal set.Tree : SetTree<'T> = tree
#if FX_NO_DEBUG_DISPLAYS
#else
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
#endif
static member Empty :Set<'T> = empty
member s.Add(x) : Set<'T> = Set<'T>(s.Comparer,SetTree.add s.Comparer x s.Tree )
member s.Remove(x) : Set<'T> = Set<'T>(s.Comparer,SetTree.remove s.Comparer x s.Tree)
member s.Count = SetTree.count s.Tree
member s.Contains(x) = SetTree.mem s.Comparer x s.Tree
member s.Iterate(x) = SetTree.iter x s.Tree
member s.Fold f z = SetTree.fold_left (fun x z -> f z x) z s.Tree
#if FX_NO_DEBUG_DISPLAYS
#else
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
#endif
member s.IsEmpty = SetTree.is_empty s.Tree
member s.Partition f : Set<'T> * Set<'T> =
match s.Tree with
| SetEmpty -> s,s
| _ -> let t1,t2 = SetTree.partition s.Comparer f s.Tree in Set<_>(s.Comparer,t1), Set<_>(s.Comparer,t2)
member s.Filter f : Set<'T> =
match s.Tree with
| SetEmpty -> s
| _ -> Set<_>(s.Comparer,SetTree.filter s.Comparer f s.Tree)
member s.Map f : Set<'U> =
let comparer = ComparisonIdentity.GetFastStructuralComparisonFunction<'U>()
Set<_>(comparer,SetTree.fold_left (fun acc k -> SetTree.add comparer (f k) acc) (SetTree<_>.SetEmpty) s.Tree)
member s.Exists f = SetTree.exists f s.Tree
member s.forall f = SetTree.for_all f s.Tree
static member (-) (a: Set<'T>, b: Set<'T>) = Set<_>.Subtract(a,b)
[<System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates")>]
static member (+) (a: Set<'T>, b: Set<'T>) = Set<_>.Union(a,b)
static member Intersection(a: Set<'T>, b: Set<'T>) : Set<'T> =
match b.Tree with
| SetEmpty -> b (* A INTER 0 = 0 *)
| _ ->
match a.Tree with
| SetEmpty -> a (* 0 INTER B = 0 *)
| _ -> Set<_>(a.Comparer,SetTree.intersection a.Comparer a.Tree b.Tree)
static member Union(a: Set<'T>, b: Set<'T>) : Set<'T> =
match b.Tree with
| SetEmpty -> a (* A U 0 = A *)
| _ ->
match a.Tree with
| SetEmpty -> b (* 0 U B = B *)
| _ -> Set<_>(a.Comparer,SetTree.union a.Comparer a.Tree b.Tree)
static member Union(sets:seq<Set<'T>>) : Set<'T> =
Seq.fold (fun s1 s2 -> Set<_>.Union(s1,s2)) Set<'T>.Empty sets
static member Intersection(sets:seq<Set<'T>>) : Set<'T> =
Seq.reduce (fun s1 s2 -> Set<_>.Intersection(s1,s2)) sets
static member Subtract(a: Set<'T>, b: Set<'T>) : Set<'T> =
match a.Tree with
| SetEmpty -> a (* 0 - B = 0 *)
| _ ->
match b.Tree with
| SetEmpty -> a (* A - 0 = A *)
| _ -> Set<_>(a.Comparer,SetTree.diff a.Comparer a.Tree b.Tree)
static member Equality(a: Set<'T>, b: Set<'T>) = (SetTree.compare a.Comparer a.Tree b.Tree = 0)
static member Compare(a: Set<'T>, b: Set<'T>) = SetTree.compare a.Comparer a.Tree b.Tree
#if FX_NO_DEBUG_DISPLAYS
#else
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
#endif
member x.Choose = SetTree.choose x.Tree
#if FX_NO_DEBUG_DISPLAYS
#else
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
#endif
member x.MinimumElement = SetTree.minimumElement x.Tree
#if FX_NO_DEBUG_DISPLAYS
#else
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
#endif
member x.MaximumElement = SetTree.maximumElement x.Tree
member x.GetNextElement(e) = SetTree.nextElem x.Comparer e x.Tree
member x.GetPreviousElement(e) = SetTree.prevElem x.Comparer e x.Tree
member x.IsSubsetOf(y: Set<'T>) = SetTree.subset x.Comparer x.Tree y.Tree
member x.IsSupersetOf(y: Set<'T>) = SetTree.subset x.Comparer y.Tree x.Tree
member x.ToList () = SetTree.to_list x.Tree
member x.ToArray () = SetTree.to_array x.Tree
member this.ComputeHashCode() =
let combineHash x y = (x <<< 1) + y + 631
let mutable res = 0
for x in this do
res <- combineHash res (hash x)
abs res
override this.GetHashCode() = this.ComputeHashCode()
override this.Equals(that) =
match that with
| :? Set<'T> as that ->
((this :> System.IComparable).CompareTo(that) = 0)
| _ -> false
interface System.IComparable with
member this.CompareTo(that: obj) = SetTree.compare this.Comparer this.Tree ((that :?> Set<'T>).Tree)
interface ICollection<'T> with
member s.Add(x) = raise (new System.NotSupportedException("ReadOnlyCollection"))
member s.Clear() = raise (new System.NotSupportedException("ReadOnlyCollection"))
member s.Remove(x) = raise (new System.NotSupportedException("ReadOnlyCollection"))
member s.Contains(x) = SetTree.mem s.Comparer x s.Tree
member s.CopyTo(arr,i) = SetTree.copyToArray s.Tree arr i
member s.get_IsReadOnly() = true
member s.get_Count() = SetTree.count s.Tree
interface IEnumerable<'T> with
member s.GetEnumerator() = SetTree.mkIEnumerator s.Tree
interface IEnumerable with
override s.GetEnumerator() = (SetTree.mkIEnumerator s.Tree :> IEnumerator)
static member Singleton(x:'T) : Set<'T> = Set<'T>.Empty.Add(x)
new (elements : seq<'T>) =
let comparer = ComparisonIdentity.GetFastStructuralComparisonFunction<'T>()
Set<_>(comparer,SetTree.of_seq comparer elements)
static member Create(elements : seq<'T>) = Set<'T>(elements)
static member FromArray(arr : 'T array) : Set<'T> =
let comparer = ComparisonIdentity.GetFastStructuralComparisonFunction<'T>()
Set<_>(comparer,SetTree.of_array comparer arr)
and
[<Sealed>]
SetDebugView<'T>(v: Set<'T>) =
#if FX_NO_DEBUG_DISPLAYS
#else
[<System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)>]
#endif
member x.Items = v |> Seq.truncate 1000 |> Seq.to_array
namespace Microsoft.FSharp.Collections
open Microsoft.FSharp.Core
open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
open Microsoft.FSharp.Core.Operators
open Microsoft.FSharp.Collections
open System.Collections
open System.Collections.Generic
open System.Diagnostics
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
[<RequireQualifiedAccess>]
module Set =
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let isEmpty (s : Set<'T>) = s.IsEmpty
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let is_empty (s : Set<'T>) = s.IsEmpty
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let contains x (s : Set<'T>) = s.Contains(x)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let mem x (s : Set<'T>) = s.Contains(x)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let add x (s : Set<'T>) = s.Add(x)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let singleton x = Set<'T>.Singleton(x)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let remove x (s : Set<'T>) = s.Remove(x)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let union (s1 : Set<'T>) (s2 : Set<'T>) = Set<'T>.Union(s1,s2)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let unionMany sets = Set<_>.Union(sets)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let union_all sets = unionMany sets
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let intersect (s1 : Set<'T>) (s2 : Set<'T>) = Set<'T>.Intersection(s1,s2)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let intersectMany sets = Set<_>.Intersection(sets)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let intersect_all sets = intersectMany sets
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let iter f (s : Set<'T>) = s.Iterate(f)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let empty<'T> : Set<'T> = Set<'T>.Empty
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let forall f (s : Set<'T>) = s.forall f
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let for_all f (s : Set<'T>) = s.forall f
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let exists f (s : Set<'T>) = s.Exists f
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let filter f (s : Set<'T>) = s.Filter f
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let partition f (s : Set<'T>) = s.Partition f
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let fold f z (s : Set<'T>) = SetTree.fold_left f z s.Tree
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let fold_left f z s = fold f z s
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let foldBack f (s : Set<'T>) z = SetTree.fold_right f s.Tree z
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let fold_right f s z = foldBack f s z
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let map f (s : Set<'T>) = s.Map f
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let count (s : Set<'T>) = s.Count
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let minimumElement (s : Set<'T>) = s.MinimumElement
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let maximumElement (s : Set<'T>) = s.MaximumElement
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let choose (s : Set<'T>) = s.Choose
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let of_list l = Set<_>(List.to_seq l)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let of_array (l : 'T array) = Set<'T>.FromArray(l)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let to_list (s : Set<'T>) = s.ToList()
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let to_array (s : Set<'T>) = s.ToArray()
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let to_seq (s : Set<'T>) = (s :> seq<'T>)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let of_seq (c : seq<_>) = Set<_>(c)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let next_elt x (s : Set<'T>) = s.GetNextElement(x)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let prev_elt x (s : Set<'T>) = s.GetPreviousElement(x)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let min_elt (s : Set<'T>) = s.MinimumElement
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let max_elt (s : Set<'T>) = s.MaximumElement
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let size (s: Set<'T>) = s.Count
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let compare (s1: Set<'T>) (s2: Set<'T>) = Set<_>.Compare(s1,s2)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let subset (s1: Set<'T>) (s2: Set<'T>) = s1.IsSubsetOf(s2)
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1709:IdentifiersShouldBeCasedCorrectly"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1707:IdentifiersShouldNotContainUnderscores"); CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
let diff (s1: Set<'T>) (s2: Set<'T>) = s1 - s2