mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-06 16:33:15 +01:00
165 lines
3.8 KiB
JavaScript
165 lines
3.8 KiB
JavaScript
function HashTable(hashCodeF, equalsF) {
|
|
this.hashCodeF = hashCodeF;
|
|
this.equalsF = equalsF;
|
|
this.setTableSize(8);
|
|
this.size = 0;
|
|
}
|
|
|
|
HashTable.prototype.hash = function(key) {
|
|
return Math.abs(this.hashCodeF(key) % this.table.length);
|
|
};
|
|
|
|
HashTable.prototype.get = function(key) {
|
|
let entry = this._findEntry(key, this._findBucket(key));
|
|
if (entry == null) return null;
|
|
return entry[1];
|
|
};
|
|
|
|
HashTable.prototype.put = function(key, value) {
|
|
if (this.size >= 0.75 * this.table.length) {
|
|
this.rebuild();
|
|
}
|
|
this._put(key, value);
|
|
};
|
|
|
|
HashTable.prototype._findBucket = function(key) {
|
|
let hash = this.hash(key);
|
|
let bucket = this.table[hash];
|
|
if (bucket === null) {
|
|
bucket = [];
|
|
this.table[hash] = bucket;
|
|
}
|
|
return bucket;
|
|
};
|
|
|
|
HashTable.prototype._findEntry = function(key, bucket) {
|
|
for (let i = 0; i < bucket.length; i++) {
|
|
if (this.equalsF(bucket[i][0], key)) {
|
|
return bucket[i];
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
HashTable.prototype._put = function(key, value) {
|
|
let bucket = this._findBucket(key);
|
|
let entry = this._findEntry(key, bucket);
|
|
if (entry == null) {
|
|
bucket.push([key, value]);
|
|
} else {
|
|
entry[1] = value;
|
|
}
|
|
this.size++;
|
|
};
|
|
|
|
HashTable.prototype.rebuild = function() {
|
|
this.size = 0;
|
|
let oldTable = this.table;
|
|
this.setTableSize(this.table.length * 2);
|
|
for (let i = 0; i < oldTable.length; i++) {
|
|
let e = oldTable[i];
|
|
if (e != null) {
|
|
for (let j = 0; j < e.length; j++) {
|
|
let bucket = e[j];
|
|
this._put(bucket[0], bucket[1]);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
HashTable.prototype.getKeys = function() {
|
|
let keys = [];
|
|
this.entries(function(k) {
|
|
keys.push(k)
|
|
});
|
|
return keys;
|
|
};
|
|
|
|
HashTable.prototype.entries = function(callback) {
|
|
for (let i = 0; i < this.table.length; i++) {
|
|
let e = this.table[i];
|
|
if (e != null) {
|
|
for (let j = 0; j < e.length; j++) {
|
|
let bucket = e[j];
|
|
callback(bucket[0], bucket[1]);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
HashTable.prototype.setTableSize = function(newSize) {
|
|
this.table = [];
|
|
for (let i = 0; i < newSize; i++) {
|
|
this.table[i] = null;
|
|
}
|
|
};
|
|
|
|
function DoubleHelper() {
|
|
this.dv = new DataView(new ArrayBuffer(8));
|
|
}
|
|
|
|
DoubleHelper.prototype.hash = function(v) {
|
|
this.dv.setFloat64(0, v);
|
|
return this.dv.getInt32(0) ^ this.dv.getInt32(4);
|
|
};
|
|
|
|
HashTable.forVector3d = function() {
|
|
let doubleHelper = new DoubleHelper();
|
|
function hash(v) {
|
|
return doubleHelper.hash(v.x) ^ doubleHelper.hash(v.y) ^ doubleHelper.hash(v.z);
|
|
}
|
|
function eq(a, b) {
|
|
return a.x === b.x && a.y === b.y && a.z === b.z;
|
|
}
|
|
return new HashTable(hash, eq);
|
|
};
|
|
|
|
HashTable.forEdge = function() {
|
|
let doubleHelper = new DoubleHelper();
|
|
function hash(v) {
|
|
return doubleHelper.hash(v[0].x) ^ doubleHelper.hash(v[0].y) ^ doubleHelper.hash(v[0].z)
|
|
^doubleHelper.hash(v[1].x) ^ doubleHelper.hash(v[1].y) ^ doubleHelper.hash(v[1].z);
|
|
}
|
|
function veq(a, b) {
|
|
return a.x === b.x && a.y === b.y && a.z === b.z;
|
|
}
|
|
function eq(e1, e2) {
|
|
let a1 = e1[0];
|
|
let b1 = e1[1];
|
|
let a2 = e2[0];
|
|
let b2 = e2[1];
|
|
return (veq(a1, a2) && veq(b1, b2)) || (veq(a1, b2) && veq(b1, a2));
|
|
}
|
|
return new HashTable(hash, eq);
|
|
};
|
|
|
|
HashTable.forVector2d = function() {
|
|
let doubleHelper = new DoubleHelper();
|
|
function hash(v) {
|
|
return doubleHelper.hash(v.x) ^ doubleHelper.hash(v.y) ;
|
|
}
|
|
function eq(a, b) {
|
|
return a.x === b.x && a.y === b.y;
|
|
}
|
|
return new HashTable(hash, eq);
|
|
};
|
|
|
|
HashTable.forDoubleArray = function() {
|
|
let doubleHelper = new DoubleHelper();
|
|
function hash(v) {
|
|
let hash = 0;
|
|
for (let i = 0; i < v.length; i++) {
|
|
hash ^= v[i];
|
|
}
|
|
return hash;
|
|
}
|
|
function eq(a, b) {
|
|
for (let i = 0; i < a.length; i++) {
|
|
if (a[i] !== b[i]) return false;
|
|
}
|
|
return true;
|
|
}
|
|
return new HashTable(hash, eq);
|
|
};
|
|
|
|
export {HashTable, DoubleHelper}
|