-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathFastDictionary.cs
More file actions
145 lines (130 loc) · 3.32 KB
/
FastDictionary.cs
File metadata and controls
145 lines (130 loc) · 3.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
using UnityEngine;
using System.Collections;
namespace FastCollections
{
/// <summary>
/// Experimenting with dictionary. Not yet functional.
/// </summary>
public class FastDictionary<TKey,TValue>
{
static int curDepth;
static int bigIndex, smallIndex, normHash, leIndex;
const int CollisionResolver = 1;
const int CollisionDepth = 5;
const int BucketCount = 64;
const int BucketSize = 64;
const int MaxItems = BucketCount * BucketSize;
ulong[] bucketAllocation = new ulong[BucketCount];
TValue[] bucketValues = new TValue[BucketCount * BucketSize];
int[] bucketHashes = new int[BucketCount * BucketSize];
//TKey[] bucketKeys = new TKey[BucketCount * BucketSize];
public bool Add (TKey key, TValue value)
{
Prime ();
return _Add (key.GetHashCode (), value);
}
private bool _Add (int hashCode, TValue item)
{
if (ForceStop)
return false;
GenerateIndexes (hashCode);
if (Shortcuts.GetBit (bucketAllocation[bigIndex],smallIndex)) {
if (bucketHashes [leIndex] == hashCode) {
return false;
}
//Resolve collision
return _Add (hashCode * CollisionResolver, item);
}
Shortcuts.SetBitTrue (ref bucketAllocation [bigIndex], smallIndex);
bucketValues [leIndex] = item;
bucketHashes [leIndex] = hashCode;
return true;
}
public bool Remove (TKey key)
{
Prime ();
return _Remove (key.GetHashCode ());
}
private bool _Remove (int hashCode)
{
if (ForceStop)
return false;
if (ConfirmSlot (hashCode)) {
Shortcuts.SetBitFalse (ref bucketAllocation [bigIndex], smallIndex);
return true;
}
return _Remove (hashCode * CollisionResolver);
}
public TValue this [TKey key] {
get {
Prime ();
return _GetValue (key.GetHashCode ());
}
}
private TValue _GetValue (int hashCode)
{
if (ForceStop)
throw new System.IndexOutOfRangeException ();
if (ConfirmSlot (hashCode))
{
return bucketValues[leIndex];
}
return _GetValue (hashCode * CollisionResolver);
}
public bool TryGetValue (TKey key, out TValue output)
{
Prime ();
return _TryGetValue (key.GetHashCode (), out output);
}
private bool _TryGetValue (int hashCode, out TValue output)
{
if (ForceStop) {
output = default(TValue);
return false;
}
if (ConfirmSlot (hashCode)) {
output = bucketValues [leIndex];
return true;
}
return _TryGetValue (hashCode * CollisionResolver, out output);
}
public bool ContainsKey (TKey key)
{
Prime ();
return _ContainsKey (key.GetHashCode ());
}
private bool _ContainsKey (int hashCode)
{
if (ForceStop)
return false;
GenerateIndexes (hashCode);
if (ConfirmSlot (hashCode))
return true;
return _ContainsKey (hashCode * CollisionResolver);
}
private static void Prime ()
{
curDepth = 0;
}
private static bool ForceStop {
get{ return (curDepth++ >= CollisionDepth);}
}
private static void GenerateIndexes (int hashCode)
{
normHash = hashCode % MaxItems;
bigIndex = normHash / BucketCount;
smallIndex = normHash % BucketSize;
leIndex = smallIndex * BucketCount + bigIndex;
}
private bool ConfirmSlot (int hashCode)
{
GenerateIndexes (hashCode);
if (Shortcuts.GetBit (bucketAllocation[bigIndex],smallIndex)) {
if (bucketHashes [leIndex] == hashCode) {
return true;
}
}
return false;
}
}
}