csharpfftfsharpintegrationinterpolationlinear-algebramathdifferentiationmatrixnumericsrandomregressionstatisticsmathnet
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.
179 lines
6.3 KiB
179 lines
6.3 KiB
// (c) Microsoft Corporation 2005-2009.
|
|
|
|
|
|
#if INTERNALIZED_POWER_PACK
|
|
namespace (* internal *) Internal.Utilities.Collections
|
|
//open Internal.Utilities.Collections
|
|
#else
|
|
namespace Microsoft.FSharp.Collections
|
|
#endif
|
|
|
|
open System
|
|
open System.Collections.Generic
|
|
open Microsoft.FSharp.Collections
|
|
|
|
// Each entry in the HashMultiMap dictionary has at least one entry. Under normal usage each entry has _only_
|
|
// one entry. So use two hash tables: one for the main entries and one for the overflow.
|
|
[<Sealed>]
|
|
type HashMultiMap<'Key,'Value>(hasheq: IEqualityComparer<'Key>,n:int) =
|
|
let firstEntries = new Dictionary<_,_>(n,hasheq);
|
|
let rest = new Dictionary<_,_>(3,hasheq);
|
|
|
|
static member Create(hasheq,n) = new HashMultiMap<'Key,'Value>(hasheq,n)
|
|
|
|
[<OverloadID("Create_size")>]
|
|
static member inline Create(n) : HashMultiMap<'Key,'Value> = HashMultiMap.Create(HashIdentity.Structural,n)
|
|
|
|
static member inline Create() : HashMultiMap<'Key,'Value> = HashMultiMap.Create(11)
|
|
|
|
[<OverloadID("Create_seq")>]
|
|
static member Create(seq : seq<'Key * 'Value>) : HashMultiMap<'Key,'Value> =
|
|
let x = new HashMultiMap<'Key,'Value>(11)
|
|
seq |> Seq.iter (fun (k,v) -> x.Add(k,v))
|
|
x
|
|
|
|
[<OverloadID("new_seq")>]
|
|
new (seq : seq<'Key * 'Value>) as x =
|
|
new HashMultiMap<'Key,'Value>(11)
|
|
then
|
|
seq |> Seq.iter (fun (k,v) -> x.Add(k,v))
|
|
|
|
[<OverloadID("new_size")>]
|
|
new (n:int) = new HashMultiMap<'Key,'Value>(HashIdentity.Structural,n)
|
|
new () = new HashMultiMap<'Key,'Value>(11)
|
|
|
|
|
|
member x.GetRest(k) =
|
|
let mutable res = []
|
|
let ok = rest.TryGetValue(k,&res)
|
|
if ok then res else []
|
|
|
|
member x.Add(y,z) =
|
|
let mutable res = Unchecked.defaultof<'Value>
|
|
let ok = firstEntries.TryGetValue(y,&res)
|
|
if ok then
|
|
rest.[y] <- res :: x.GetRest(y)
|
|
firstEntries.[y] <- z
|
|
|
|
member x.Clear() =
|
|
firstEntries.Clear()
|
|
rest.Clear()
|
|
|
|
member x.FirstEntries = firstEntries
|
|
member x.Rest = rest
|
|
member x.Copy() =
|
|
let res = HashMultiMap<'Key,'Value>.Create(firstEntries.Comparer, firstEntries.Count)
|
|
for kvp in firstEntries do
|
|
res.FirstEntries.Add(kvp.Key,kvp.Value)
|
|
for kvp in rest do
|
|
res.Rest.Add(kvp.Key,kvp.Value)
|
|
res
|
|
|
|
member x.Item
|
|
with get(y : 'Key) =
|
|
let mutable res = Unchecked.defaultof<'Value>
|
|
let ok = firstEntries.TryGetValue(y,&res)
|
|
if ok then res else raise (new System.Collections.Generic.KeyNotFoundException("The item was not found in collection"))
|
|
and set (y:'Key) (z:'Value) =
|
|
x.Replace(y,z)
|
|
|
|
member x.FindAll(y) =
|
|
let mutable res = Unchecked.defaultof<'Value>
|
|
let ok = firstEntries.TryGetValue(y,&res)
|
|
if ok then res :: x.GetRest(y) else []
|
|
|
|
member x.Fold f acc =
|
|
let mutable res = acc
|
|
for kvp in firstEntries do
|
|
res <- f kvp.Key kvp.Value res
|
|
match x.GetRest(kvp.Key) with
|
|
| [] -> ()
|
|
| rest ->
|
|
for z in rest do
|
|
res <- f kvp.Key z res
|
|
res
|
|
|
|
member x.Iterate(f) =
|
|
for kvp in firstEntries do
|
|
f kvp.Key kvp.Value
|
|
match x.GetRest(kvp.Key) with
|
|
| [] -> ()
|
|
| rest ->
|
|
for z in rest do
|
|
f kvp.Key z
|
|
|
|
member x.Contains(y) = firstEntries.ContainsKey(y)
|
|
|
|
member x.ContainsKey(y) = firstEntries.ContainsKey(y)
|
|
|
|
member x.Remove(y) =
|
|
let mutable res = Unchecked.defaultof<'Value>
|
|
let ok = firstEntries.TryGetValue(y,&res)
|
|
// Note, if not ok then nothing to remove - nop
|
|
if ok then
|
|
// We drop the FirstEntry. Here we compute the new FirstEntry and residue MoreEntries
|
|
let mutable res = []
|
|
let ok = rest.TryGetValue(y,&res)
|
|
if ok then
|
|
match res with
|
|
| [h] ->
|
|
firstEntries.[y] <- h;
|
|
rest.Remove(y) |> ignore
|
|
| (h::t) ->
|
|
firstEntries.[y] <- h
|
|
rest.[y] <- t
|
|
| _ ->
|
|
// note: broken invariant
|
|
()
|
|
else
|
|
firstEntries.Remove(y) |> ignore
|
|
|
|
member x.Replace(y,z) =
|
|
firstEntries.[y] <- z
|
|
|
|
member x.TryFind(y) =
|
|
let mutable res = Unchecked.defaultof<'Value>
|
|
let ok = firstEntries.TryGetValue(y,&res)
|
|
if ok then Some(res) else None
|
|
|
|
member x.Count = firstEntries.Count
|
|
|
|
interface IEnumerable<KeyValuePair<'Key, 'Value>> with
|
|
member s.GetEnumerator() =
|
|
let elems = new System.Collections.Generic.List<_>(firstEntries.Count + rest.Count)
|
|
for kvp in firstEntries do
|
|
elems.Add(kvp)
|
|
for z in s.GetRest(kvp.Key) do
|
|
elems.Add(KeyValuePair(kvp.Key, z))
|
|
(elems.GetEnumerator() :> IEnumerator<_>)
|
|
|
|
interface System.Collections.IEnumerable with
|
|
member s.GetEnumerator() = ((s :> seq<_>).GetEnumerator() :> System.Collections.IEnumerator)
|
|
|
|
interface IDictionary<'Key, 'Value> with
|
|
member s.Item
|
|
with get x = s.[x]
|
|
and set x v = s.[x] <- v
|
|
|
|
member s.Keys = ([| for kvp in s -> kvp.Key |] :> ICollection<'Key>)
|
|
member s.Values = ([| for kvp in s -> kvp.Value |] :> ICollection<'Value>)
|
|
member s.Add(k,v) = s.[k] <- v
|
|
member s.ContainsKey(k) = s.ContainsKey(k)
|
|
member s.TryGetValue(k,r) = if s.ContainsKey(k) then (r <- s.[k]; true) else false
|
|
member s.Remove(k:'Key) =
|
|
let res = s.ContainsKey(k) in
|
|
s.Remove(k); res
|
|
|
|
interface ICollection<KeyValuePair<'Key, 'Value>> with
|
|
member s.Add(x) = s.[x.Key] <- x.Value
|
|
member s.Clear() = s.Clear()
|
|
member s.Remove(x) =
|
|
let res = s.ContainsKey(x.Key) in
|
|
if res && s.[x.Key] = x.Value then
|
|
s.Remove(x.Key);
|
|
res
|
|
member s.Contains(x) = s.ContainsKey(x.Key) && s.[x.Key] = x.Value
|
|
member s.CopyTo(arr,arrIndex) = s |> Seq.iteri (fun j x -> arr.[arrIndex+j] <- x)
|
|
member s.IsReadOnly = false
|
|
member s.Count = s.Count
|
|
|
|
|