|
@@ -4,8 +4,13 @@ namespace Invercargill {
|
|
|
|
|
|
public class Set<T> : Collection<T> {
|
|
public class Set<T> : Collection<T> {
|
|
|
|
|
|
- private Vector<T> items;
|
|
|
|
- private Vector<Series<int>> buckets;
|
|
|
|
|
|
+ private uint[] buckets;
|
|
|
|
+ private T[] items;
|
|
|
|
+ private int n_items = 0;
|
|
|
|
+ private int n_buckets = 10000000;
|
|
|
|
+ private int n_collissions = 0;
|
|
|
|
+ private SafeReadFunc<T>? safe_read;
|
|
|
|
+ private SafeWriteFunc<T>? safe_write;
|
|
private HashDelegate<T> hash_func;
|
|
private HashDelegate<T> hash_func;
|
|
private EqualityDelegate<T> equal_func;
|
|
private EqualityDelegate<T> equal_func;
|
|
|
|
|
|
@@ -20,30 +25,69 @@ namespace Invercargill {
|
|
private void setup(HashDelegate<T>? value_hash_func = null, EqualityDelegate<T>? value_equal_func = null) {
|
|
private void setup(HashDelegate<T>? value_hash_func = null, EqualityDelegate<T>? value_equal_func = null) {
|
|
hash_func = value_hash_func ?? Operators.hash<T>();
|
|
hash_func = value_hash_func ?? Operators.hash<T>();
|
|
equal_func = value_equal_func ?? Operators.equality<T>();
|
|
equal_func = value_equal_func ?? Operators.equality<T>();
|
|
- items = new Vector<T>();
|
|
|
|
- buckets = new Vector<Series<int>>();
|
|
|
|
- buckets.add_all(range(0, 4096).select<Series<int>>(i => new Series<int>()));
|
|
|
|
|
|
+ safe_read = get_safe_read_function_for<T>();
|
|
|
|
+ safe_write = get_safe_write_function_for<T>();
|
|
|
|
+ buckets = new uint[n_buckets];
|
|
|
|
+ items = new T[n_buckets];
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void ensure_room_for_items(int count) {
|
|
|
|
+ if(items.length <= n_items + count) {
|
|
|
|
+ items.resize(items.length * 2);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void ensure_room_for_bucket(uint index) {
|
|
|
|
+ var target = buckets.length;
|
|
|
|
+ while(target <= index) {
|
|
|
|
+ target = buckets.length * 2;
|
|
|
|
+ }
|
|
|
|
+ if(target != buckets.length) {
|
|
|
|
+ buckets.resize(target);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void double_buckets() {
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private T get_item(uint index) {
|
|
|
|
+ if(index == 0) {
|
|
|
|
+ assert_not_reached();
|
|
|
|
+ }
|
|
|
|
+ return safe_read(items, (int)index-1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private uint add_item(T item) {
|
|
|
|
+ n_items++;
|
|
|
|
+ ensure_room_for_items(1);
|
|
|
|
+ safe_write(items, (int)n_items-1, item);
|
|
|
|
+ return n_items;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private uint bucket_for(T item) {
|
|
|
|
+ var hash = hash_func(item);
|
|
|
|
+ return hash % n_buckets;
|
|
|
|
+ }
|
|
|
|
|
|
public override Tracker<T> get_tracker () {
|
|
public override Tracker<T> get_tracker () {
|
|
- return items.get_tracker();
|
|
|
|
|
|
+ return range(0, n_items).select<T>(i => safe_read(items, i)).get_tracker();
|
|
}
|
|
}
|
|
|
|
|
|
public override void add (T item) {
|
|
public override void add (T item) {
|
|
- var index = (int)bucket_for(item);
|
|
|
|
- var bucket = buckets.get_or_default(index);
|
|
|
|
- if(bucket != null && bucket.any(i => equal_func(i, item)))
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- if(bucket == null) {
|
|
|
|
- bucket = new Series<int>();
|
|
|
|
- buckets[index] = bucket;
|
|
|
|
|
|
+ var bucket_index = bucket_for(item);
|
|
|
|
+ while(buckets[bucket_index] != 0) {
|
|
|
|
+ if(equal_func(get_item(buckets[bucket_index]), item)) {
|
|
|
|
+ //set_item(bucket_index, item); MAYBE?
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ bucket_index++;
|
|
|
|
+ n_collissions++;
|
|
|
|
+ ensure_room_for_bucket(bucket_index);
|
|
}
|
|
}
|
|
-
|
|
|
|
- var item_index = items.count();
|
|
|
|
- items.add(item);
|
|
|
|
- bucket.add(item_index);
|
|
|
|
|
|
+
|
|
|
|
+ buckets[bucket_index] = add_item(item);
|
|
}
|
|
}
|
|
|
|
|
|
public override void add_all (Enumerable<T> items) {
|
|
public override void add_all (Enumerable<T> items) {
|
|
@@ -68,40 +112,40 @@ namespace Invercargill {
|
|
return new_set;
|
|
return new_set;
|
|
}
|
|
}
|
|
|
|
|
|
- public new T? find(T item) {
|
|
|
|
- var bucket = buckets.get_or_default((int)bucket_for(item));
|
|
|
|
- if(bucket == null)
|
|
|
|
- return null;
|
|
|
|
|
|
+ // public new T? find(T item) {
|
|
|
|
+ // var bucket = buckets.get_or_default((int)bucket_for(item));
|
|
|
|
+ // if(bucket == null)
|
|
|
|
+ // return null;
|
|
|
|
|
|
- foreach (var index in bucket) {
|
|
|
|
- var result = items[index];
|
|
|
|
- if(equal_func(result, item)) {
|
|
|
|
- return result;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
|
|
+ // foreach (var index in bucket) {
|
|
|
|
+ // var result = items[index];
|
|
|
|
+ // if(equal_func(result, item)) {
|
|
|
|
+ // return result;
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // return null;
|
|
|
|
+ // }
|
|
|
|
|
|
public override void remove_first_where (Invercargill.PredicateDelegate<T> predicate) {
|
|
public override void remove_first_where (Invercargill.PredicateDelegate<T> predicate) {
|
|
remove(first_or_default(predicate));
|
|
remove(first_or_default(predicate));
|
|
}
|
|
}
|
|
|
|
|
|
public override void remove_where (Invercargill.PredicateDelegate<T> predicate) {
|
|
public override void remove_where (Invercargill.PredicateDelegate<T> predicate) {
|
|
- items.where(predicate).iterate(remove);
|
|
|
|
|
|
+ // items.where(predicate).iterate(remove);
|
|
}
|
|
}
|
|
|
|
|
|
public void remove(T item) {
|
|
public void remove(T item) {
|
|
- var bucket = buckets.get_or_default((int)bucket_for(item));
|
|
|
|
- if(bucket == null)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- foreach (var index in bucket) {
|
|
|
|
- var result = items[index];
|
|
|
|
- if(equal_func(result, item)) {
|
|
|
|
- bucket.remove_first_where(i => i == index);
|
|
|
|
- items.remove(index);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ // var bucket = buckets.get_or_default((int)bucket_for(item));
|
|
|
|
+ // if(bucket == null)
|
|
|
|
+ // return;
|
|
|
|
+
|
|
|
|
+ // foreach (var index in bucket) {
|
|
|
|
+ // var result = items[index];
|
|
|
|
+ // if(equal_func(result, item)) {
|
|
|
|
+ // bucket.remove_first_where(i => i == index);
|
|
|
|
+ // items.remove(index);
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
}
|
|
}
|
|
|
|
|
|
public void remove_all(Enumerable<T> items) {
|
|
public void remove_all(Enumerable<T> items) {
|
|
@@ -114,14 +158,12 @@ namespace Invercargill {
|
|
}
|
|
}
|
|
|
|
|
|
public bool has(T item) {
|
|
public bool has(T item) {
|
|
- var bucket = buckets.get_or_default((int)bucket_for(item));
|
|
|
|
- return bucket != null && bucket.any(i => equal_func(i, item));
|
|
|
|
|
|
+ // var bucket = buckets.get_or_default((int)bucket_for(item));
|
|
|
|
+ // return bucket != null && bucket.any(i => equal_func(i, item));
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
|
|
|
|
- private uint bucket_for(T item) {
|
|
|
|
- var hash = hash_func(item);
|
|
|
|
- return hash % buckets.count();
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|