Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions DummyProject/DummyProject.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32407.343
MinimumVisualStudioVersion = 10.0.40219.1
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "SmallValueSet", "..\SmallValueSet\SmallValueSet.fsproj", "{3F5A0AE0-8CF7-4853-BE61-CA19155EE9A5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3F5A0AE0-8CF7-4853-BE61-CA19155EE9A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3F5A0AE0-8CF7-4853-BE61-CA19155EE9A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3F5A0AE0-8CF7-4853-BE61-CA19155EE9A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3F5A0AE0-8CF7-4853-BE61-CA19155EE9A5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2F960B42-920E-45EE-B358-662E67BE68B5}
EndGlobalSection
EndGlobal
101 changes: 101 additions & 0 deletions SmallValueSet/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,88 @@ type SmallSetInt64 (newValues: int64 seq) =
member _.Values () =
seq { for i in 0 .. count -> values[i] }

/// An array backed Set to be used with Value types where the
/// number of elements is small. It is meant to have an API
/// that is compatible with the HashSet<'T> collection
type SmallSetGenericIEquatable<'T when 'T :> System.IEquatable<'T>> (newValues: 'T seq) =

let mutable count = Seq.length newValues
let mutable values = Array.zeroCreate (count * 2)
do newValues |> Seq.iteri (fun i v -> values[i] <- v)

/// Adds an element to the SmallSet and returns a bool
/// indicating whether the element was added
member _.Add(newValue: 'T) =
let mutable exists = false
let mutable i = 0

while i < count && (not exists) do
exists <- (values.[i]:>IEquatable<'T>).Equals(newValue)
i <- i + 1

// We only need to add the element if it does not exist
if not exists then

// Check if we have capacity in values to add the value
if count < values.Length then
// Add the new value to the end
values[count] <- newValue
// Update the number of elements stored in the SmallSet
count <- count + 1

else
// Create a new, larger array to contain the values
let newValues = Array.zeroCreate (values.Length * 2)
// Add the values from the previous store to the new one
values
|> Array.iteri (fun i v -> newValues[i] <- v)
// Add the new value to the end
newValues[values.Length] <- newValue
// Update the number of elements held by the SmallSet
count <- values.Length + 1
// Swap out the internal store
values <- newValues

exists

/// Removes an element from the SmallSet returning a bool
/// indicating whether the SmallSet contained the element
member _.Remove(value: 'T) =

let mutable i = 0
let mutable isFound = false

while i < count && (not isFound) do

// Check if we have found the value of interest
if (values[i]:>IEquatable<'T>).Equals(value) then
// We overwrite the removed value with the last value
// in the SmallSet
values[i] <- values[count - 1]
// We decrement the count to indicate the new number of
// elements in the small set
count <- count - 1
// We update the isFound flag to break out of the loop
isFound <- true

i <- i + 1

isFound

/// Returns an int indicating the number of elements in the SmallSet
member _.Count = count

/// Retrieve an item by index from the SmallSet
member _.Item
with get k =
if k > count - 1 then
raise (IndexOutOfRangeException ())
else
values[k]

// A simple way to iterate through the values in the SmallSet.
member _.Values () =
seq { for i in 0 .. count -> values[i] }

[<MemoryDiagnoser>]
type Benchmarks () =
Expand All @@ -350,6 +432,7 @@ type Benchmarks () =
let smallSetFastComparer = SmallSetFastComparer values
let smallSetEqualityComparer = SmallSetEqualityComparer values
let smallSetInt64 = SmallSetInt64 values
let smallSetGenericIEquatable = SmallSetGenericIEquatable values

[<Benchmark>]
member _.HashSetAdd () =
Expand Down Expand Up @@ -396,6 +479,15 @@ type Benchmarks () =

result

[<Benchmark>]
member _.SmallSetGenericIEquatableAdd () =
let mutable result = false

for elem in addValues do
result <- smallSetGenericIEquatable.Add elem

result

[<Benchmark>]
member _.HashSetRemove () =
let mutable result = false
Expand Down Expand Up @@ -441,6 +533,15 @@ type Benchmarks () =

result

[<Benchmark>]
member _.SmallSetGenericIEquatableRemove () =
let mutable result = false

for elem in removeValues do
result <- smallSetGenericIEquatable.Remove elem

result



let args = Environment.GetCommandLineArgs()[1..]
Expand Down