@graphty/algorithms
Version:
Graph algorithms library for browser environments implemented in TypeScript
1,459 lines • 346 kB
JavaScript
class Graph {
constructor(config = {}) {
this.config = {
directed: false,
allowSelfLoops: true,
allowParallelEdges: false,
...config
};
this.nodeMap = /* @__PURE__ */ new Map();
this.adjacencyList = /* @__PURE__ */ new Map();
this.incomingEdges = /* @__PURE__ */ new Map();
this.edgeCount = 0;
}
/**
* Add a node to the graph
*/
addNode(id, data) {
if (!this.nodeMap.has(id)) {
this.nodeMap.set(id, { id, data });
this.adjacencyList.set(id, /* @__PURE__ */ new Map());
if (this.config.directed) {
this.incomingEdges.set(id, /* @__PURE__ */ new Map());
}
}
}
/**
* Remove a node from the graph
*/
removeNode(id) {
if (!this.nodeMap.has(id)) {
return false;
}
const outgoingEdges = this.adjacencyList.get(id);
if (outgoingEdges) {
for (const targetId of Array.from(outgoingEdges.keys())) {
this.removeEdge(id, targetId);
}
}
if (this.config.directed) {
const incomingEdges = this.incomingEdges.get(id);
if (incomingEdges) {
for (const sourceId of Array.from(incomingEdges.keys())) {
this.removeEdge(sourceId, id);
}
}
} else {
for (const [nodeId, edges] of Array.from(this.adjacencyList)) {
if (edges.has(id)) {
this.removeEdge(nodeId, id);
}
}
}
this.nodeMap.delete(id);
this.adjacencyList.delete(id);
if (this.config.directed) {
this.incomingEdges.delete(id);
}
return true;
}
/**
* Add an edge to the graph
*/
addEdge(source, target, weight = 1, data) {
this.addNode(source);
this.addNode(target);
if (!this.config.allowSelfLoops && source === target) {
throw new Error("Self-loops are not allowed in this graph");
}
if (!this.config.allowParallelEdges && this.hasEdge(source, target)) {
throw new Error("Parallel edges are not allowed in this graph");
}
const edge = { source, target, weight, data };
const sourceAdjacency = this.adjacencyList.get(source);
if (sourceAdjacency) {
sourceAdjacency.set(target, edge);
}
if (this.config.directed) {
const targetIncoming = this.incomingEdges.get(target);
if (targetIncoming) {
targetIncoming.set(source, edge);
}
} else {
if (source !== target) {
const reverseEdge = { source: target, target: source, weight, data };
const targetAdjacency = this.adjacencyList.get(target);
if (targetAdjacency) {
targetAdjacency.set(source, reverseEdge);
}
}
}
this.edgeCount++;
}
/**
* Remove an edge from the graph
*/
removeEdge(source, target) {
const sourceEdges = this.adjacencyList.get(source);
if (!sourceEdges?.has(target)) {
return false;
}
sourceEdges.delete(target);
if (this.config.directed) {
const targetIncoming = this.incomingEdges.get(target);
if (targetIncoming) {
targetIncoming.delete(source);
}
} else {
const targetEdges = this.adjacencyList.get(target);
if (targetEdges) {
targetEdges.delete(source);
}
}
this.edgeCount--;
return true;
}
/**
* Check if a node exists in the graph
*/
hasNode(id) {
return this.nodeMap.has(id);
}
/**
* Check if an edge exists in the graph
*/
hasEdge(source, target) {
const sourceEdges = this.adjacencyList.get(source);
return sourceEdges ? sourceEdges.has(target) : false;
}
/**
* Get a node by ID
*/
getNode(id) {
return this.nodeMap.get(id);
}
/**
* Get an edge by source and target
*/
getEdge(source, target) {
const sourceEdges = this.adjacencyList.get(source);
return sourceEdges ? sourceEdges.get(target) : void 0;
}
/**
* Get the number of nodes in the graph
*/
get nodeCount() {
return this.nodeMap.size;
}
/**
* Get the number of edges in the graph
*/
get totalEdgeCount() {
return this.edgeCount;
}
/**
* Check if the graph is directed
*/
get isDirected() {
return this.config.directed;
}
/**
* Get all nodes in the graph
*/
nodes() {
return this.nodeMap.values();
}
/**
* Get all edges in the graph
*/
*edges() {
for (const [source, edges] of this.adjacencyList) {
for (const edge of edges.values()) {
if (!this.config.directed && source > edge.target) {
continue;
}
yield edge;
}
}
}
/**
* Get neighbors of a node (outgoing edges)
*/
neighbors(nodeId) {
const edges = this.adjacencyList.get(nodeId);
return edges ? edges.keys() : (/* @__PURE__ */ new Map()).keys();
}
/**
* Get incoming neighbors of a node (directed graphs only)
*/
inNeighbors(nodeId) {
if (!this.config.directed) {
return this.neighbors(nodeId);
}
const edges = this.incomingEdges.get(nodeId);
return edges ? edges.keys() : (/* @__PURE__ */ new Map()).keys();
}
/**
* Get outgoing neighbors of a node
*/
outNeighbors(nodeId) {
return this.neighbors(nodeId);
}
/**
* Get the degree of a node
*/
degree(nodeId) {
if (this.config.directed) {
return this.inDegree(nodeId) + this.outDegree(nodeId);
}
const edges = this.adjacencyList.get(nodeId);
return edges ? edges.size : 0;
}
/**
* Get the in-degree of a node
*/
inDegree(nodeId) {
if (!this.config.directed) {
return this.degree(nodeId);
}
const edges = this.incomingEdges.get(nodeId);
return edges ? edges.size : 0;
}
/**
* Get the out-degree of a node
*/
outDegree(nodeId) {
const edges = this.adjacencyList.get(nodeId);
return edges ? edges.size : 0;
}
/**
* Create a copy of the graph
*/
clone() {
const cloned = new Graph(this.config);
for (const node of this.nodeMap.values()) {
cloned.addNode(node.id, node.data ? { ...node.data } : void 0);
}
for (const edge of this.edges()) {
cloned.addEdge(
edge.source,
edge.target,
edge.weight,
edge.data ? { ...edge.data } : void 0
);
}
return cloned;
}
/**
* Get graph configuration
*/
getConfig() {
return { ...this.config };
}
/**
* Clear all nodes and edges from the graph
*/
clear() {
this.nodeMap.clear();
this.adjacencyList.clear();
this.incomingEdges.clear();
this.edgeCount = 0;
}
/**
* Get the number of unique edges in the graph
* For undirected graphs, each edge is counted once
*/
get uniqueEdgeCount() {
if (this.config.directed) {
return this.edgeCount;
}
let count = 0;
for (const _edge of this.edges()) {
count++;
}
return count;
}
}
var lib = {};
var SparseTypedFastBitSet = {};
var utils = {};
var hasRequiredUtils;
function requireUtils() {
if (hasRequiredUtils) return utils;
hasRequiredUtils = 1;
Object.defineProperty(utils, "__esModule", { value: true });
utils.hammingWeight4 = utils.hammingWeight = void 0;
function hammingWeight(v) {
v -= v >>> 1 & 1431655765;
v = (v & 858993459) + (v >>> 2 & 858993459);
return (v + (v >>> 4) & 252645135) * 16843009 >>> 24;
}
utils.hammingWeight = hammingWeight;
function hammingWeight4(v1, v2, v3, v4) {
v1 -= v1 >>> 1 & 1431655765;
v2 -= v2 >>> 1 & 1431655765;
v3 -= v3 >>> 1 & 1431655765;
v4 -= v4 >>> 1 & 1431655765;
v1 = (v1 & 858993459) + (v1 >>> 2 & 858993459);
v2 = (v2 & 858993459) + (v2 >>> 2 & 858993459);
v3 = (v3 & 858993459) + (v3 >>> 2 & 858993459);
v4 = (v4 & 858993459) + (v4 >>> 2 & 858993459);
v1 = v1 + (v1 >>> 4) & 252645135;
v2 = v2 + (v2 >>> 4) & 252645135;
v3 = v3 + (v3 >>> 4) & 252645135;
v4 = v4 + (v4 >>> 4) & 252645135;
return (v1 + v2 + v3 + v4) * 16843009 >>> 24;
}
utils.hammingWeight4 = hammingWeight4;
return utils;
}
var hasRequiredSparseTypedFastBitSet;
function requireSparseTypedFastBitSet() {
if (hasRequiredSparseTypedFastBitSet) return SparseTypedFastBitSet;
hasRequiredSparseTypedFastBitSet = 1;
var __values = SparseTypedFastBitSet && SparseTypedFastBitSet.__values || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function() {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(SparseTypedFastBitSet, "__esModule", { value: true });
SparseTypedFastBitSet.SparseTypedFastBitSet = void 0;
var utils_1 = requireUtils();
var Type;
(function(Type2) {
Type2[Type2["ARRAY"] = 0] = "ARRAY";
Type2[Type2["BITSET"] = 1] = "BITSET";
Type2[Type2["MIXED"] = 2] = "MIXED";
})(Type || (Type = {}));
function isIterable(obj) {
if (obj) {
return obj[Symbol.iterator] !== void 0;
}
return false;
}
var SparseTypedFastBitSet$1 = (
/** @class */
function() {
function SparseTypedFastBitSet2(iterable, data) {
var e_1, _a;
if (data === void 0) {
data = new Uint32Array(8);
}
this.data = data;
this.arraySize = 0;
if (isIterable(iterable)) {
try {
for (var iterable_1 = __values(iterable), iterable_1_1 = iterable_1.next(); !iterable_1_1.done; iterable_1_1 = iterable_1.next()) {
var key = iterable_1_1.value;
this.add(key);
}
} catch (e_1_1) {
e_1 = { error: e_1_1 };
} finally {
try {
if (iterable_1_1 && !iterable_1_1.done && (_a = iterable_1.return)) _a.call(iterable_1);
} finally {
if (e_1) throw e_1.error;
}
}
}
}
Object.defineProperty(SparseTypedFastBitSet2.prototype, "words", {
get: function() {
if (this.arraySize !== -1) {
this.data = this.toBitset();
this.arraySize = -1;
}
return this.data;
},
enumerable: false,
configurable: true
});
SparseTypedFastBitSet2.prototype.toBitset = function() {
var array = this.data;
var count = array[0] + 32 >>> 5;
var newWords = new Uint32Array(count << 1);
for (var i = 0; i < this.arraySize; i++) {
var add = array[i];
newWords[add >>> 5] |= 1 << add;
}
return newWords;
};
SparseTypedFastBitSet2.prototype.add = function(index) {
var type = this.resize(index);
if (type === Type.ARRAY) {
var array = this.data;
if (this.arraySize === 0) {
array[this.arraySize++] = index;
return;
}
var offset = array.indexOf(index);
if (offset === -1 || offset >= this.arraySize) {
var biggest = array[0];
if (index > biggest) {
array[0] = index;
array[this.arraySize++] = biggest;
} else {
array[this.arraySize++] = index;
}
}
} else {
this.data[index >>> 5] |= 1 << index;
}
};
SparseTypedFastBitSet2.prototype.flip = function(index) {
var type = this.resize(index);
if (type === Type.ARRAY) {
var array = this.data;
var arrayIndex = array.indexOf(index);
if (arrayIndex === -1) {
if (this.arraySize > 0 && index > array[0]) {
array[this.arraySize++] = array[0];
array[0] = index;
} else {
array[this.arraySize++] = index;
}
} else {
if (arrayIndex === 0 && this.arraySize > 1) {
var largest = array[1];
var largestIndex = 1;
for (var i = 2; i < this.arraySize; i++) {
if (array[i] > largest) {
largest = array[i];
largestIndex = i;
}
}
array[0] = array[largestIndex];
array[largestIndex] = array[--this.arraySize];
} else {
array[arrayIndex] = array[--this.arraySize];
}
}
} else {
this.data[index >>> 5] ^= 1 << index;
}
};
SparseTypedFastBitSet2.prototype.clear = function() {
this.arraySize = 0;
this.data = new Uint32Array(8);
};
SparseTypedFastBitSet2.prototype.remove = function(index) {
var type = this.resize(index);
if (type === Type.ARRAY) {
var array = this.data;
var arrayIndex = array.indexOf(index);
if (arrayIndex !== -1 && arrayIndex < this.arraySize) {
if (arrayIndex == this.arraySize - 1) {
this.arraySize--;
} else if (arrayIndex === 0 && this.arraySize > 1) {
var largest = array[1];
var largestIndex = 1;
for (var i = 2; i < this.arraySize; i++) {
if (array[i] > largest) {
largest = array[i];
largestIndex = i;
}
}
array[0] = array[largestIndex];
array[largestIndex] = array[--this.arraySize];
} else {
array[arrayIndex] = array[--this.arraySize];
}
}
} else {
this.data[index >>> 5] &= ~(1 << index);
}
};
SparseTypedFastBitSet2.prototype.addRange = function(start, end) {
if (start >= end) {
return;
}
var type = this.resize(end, end - start - 1);
if (type === Type.ARRAY) {
var array = this.data;
var biggestAdd = end-- - 1;
if (this.arraySize === 0) {
array[this.arraySize++] = biggestAdd;
} else {
var offset = array.indexOf(biggestAdd);
if (offset === -1 || offset >= this.arraySize) {
var biggest = array[0];
if (biggestAdd > biggest) {
array[0] = biggestAdd;
array[this.arraySize++] = biggest;
} else {
array[this.arraySize++] = biggestAdd;
}
}
}
for (; start < end; start++) {
var offset = array.indexOf(start);
if (offset === -1 || offset >= this.arraySize) {
array[this.arraySize++] = start;
}
}
} else {
var words = this.data;
var firstword = start >> 5;
var endword = end - 1 >> 5;
if (firstword === endword) {
words[firstword] |= -1 << start & -1 >>> -end;
return;
}
words[firstword] |= -1 << start;
words.fill(-1, firstword + 1, endword);
words[endword] |= -1 >>> -end;
}
};
SparseTypedFastBitSet2.prototype.removeRange = function(start, end) {
if (start >= end) {
return;
}
if (this.arraySize !== -1) {
var array = this.data;
var findBiggest = false;
for (var i = 0; i < this.arraySize; i++) {
if (array[i] >= start && array[i] < end) {
if (i === 0) {
findBiggest = true;
}
array[i--] = array[--this.arraySize];
}
}
if (findBiggest && this.arraySize > 1) {
var largest = array[0];
var largestIndex = 0;
for (var i = 1; i < this.arraySize; i++) {
if (array[i] > largest) {
largest = array[i];
largestIndex = i;
}
}
var current = array[0];
array[0] = array[largestIndex];
array[largestIndex] = current;
}
} else {
var words = this.data;
start = Math.min(start, (words.length << 5) - 1);
end = Math.min(end, (words.length << 5) - 1);
var firstword = start >> 5;
var endword = end - 1 >> 5;
if (firstword === endword) {
words[firstword] &= ~(-1 << start & -1 >>> -end);
return;
}
words[firstword] &= ~(-1 << start);
words.fill(0, firstword + 1, endword);
words[endword] &= ~(-1 >>> -end);
}
};
SparseTypedFastBitSet2.prototype.isEmpty = function() {
if (this.arraySize === 0) {
return true;
}
if (this.arraySize > 0) {
return false;
}
var words = this.data;
var c = words.length;
for (var i = 0; i < c; i++) {
if (words[i] !== 0)
return false;
}
return true;
};
SparseTypedFastBitSet2.prototype.has = function(index) {
if (this.arraySize === -1) {
return (this.data[index >>> 5] & 1 << index) !== 0;
} else {
var offset = this.data.indexOf(index);
return offset !== -1 && offset < this.arraySize;
}
};
SparseTypedFastBitSet2.prototype.checkedAdd = function(index) {
var type = this.resize(index);
if (type === Type.ARRAY) {
var array = this.data;
if (this.arraySize === 0) {
array[this.arraySize++] = index;
return 1;
}
var offset = array.indexOf(index);
if (offset === -1 || offset >= this.arraySize) {
var biggest = array[0];
if (index > biggest) {
array[0] = index;
array[this.arraySize++] = biggest;
} else {
array[this.arraySize++] = index;
}
return 1;
}
return 0;
} else {
var words = this.data;
var word = words[index >>> 5];
var newword = word | 1 << index;
words[index >>> 5] = newword;
return (newword ^ word) >>> index;
}
};
SparseTypedFastBitSet2.prototype.trim = function() {
var size = this.size();
if (this.arraySize === -1) {
var words = this.data;
var nl = words.length;
while (nl > 0 && words[nl - 1] === 0) {
nl--;
}
if (size < nl) {
var newArray = new Uint32Array(size);
var pos = 0 | 0;
var c = words.length;
for (var k = 0; k < c; ++k) {
var w = words[k];
while (w != 0) {
var t = w & -w;
newArray[pos++] = (k << 5) + (0, utils_1.hammingWeight)(t - 1 | 0);
w ^= t;
}
}
var first = newArray[0];
newArray[0] = newArray[size - 1];
newArray[size - 1] = first;
this.data = newArray;
this.arraySize = size;
} else {
this.data = words.slice(0, nl);
}
} else {
if (this.arraySize > 0 && this.data[0] >>> 5 < size) {
var count = this.data[0] + 32 >>> 5;
var newWords = new Uint32Array(count);
for (var i = 0; i < this.arraySize; i++) {
var add = this.data[i];
newWords[add >>> 5] |= 1 << add;
}
this.data = newWords;
this.arraySize = -1;
} else {
this.data = this.data.slice(0, this.arraySize);
}
}
};
SparseTypedFastBitSet2.prototype.resize = function(index, capacity) {
if (capacity === void 0) {
capacity = 0;
}
if (this.arraySize === -1) {
var words = this.data;
if (words.length << 5 > index)
return Type.BITSET;
var count = index + 32 >>> 5;
var newwords = new Uint32Array(count << 1);
newwords.set(words);
this.data = newwords;
return Type.BITSET;
} else {
var array = this.data;
if (this.arraySize + capacity < array.length) {
return Type.ARRAY;
}
if (array.length + capacity < 256) {
var newData = new Uint32Array(array.length + capacity << 1);
newData.set(array);
this.data = newData;
return Type.ARRAY;
} else {
var count = Math.max(array[0], index) + 32 >>> 5;
if (count > array.length + capacity && array.length + capacity << 1 < 1024) {
var newData = new Uint32Array(array.length + capacity << 1);
newData.set(array);
this.data = newData;
return Type.ARRAY;
} else {
var newwords = new Uint32Array(count << 1);
for (var i = 0; i < this.arraySize; i++) {
var add = array[i];
newwords[add >>> 5] |= 1 << add;
}
this.arraySize = -1;
this.data = newwords;
return Type.BITSET;
}
}
}
};
SparseTypedFastBitSet2.prototype.size = function() {
if (this.arraySize === -1) {
var words = this.data;
var answer = 0;
var c = words.length;
var k = 0 | 0;
for (; k + 4 < c; k += 4) {
answer += (0, utils_1.hammingWeight4)(words[k] | 0, words[k + 1] | 0, words[k + 2] | 0, words[k + 3] | 0);
}
for (; k < c; ++k) {
answer += (0, utils_1.hammingWeight)(words[k] | 0);
}
return answer;
} else {
return this.arraySize;
}
};
SparseTypedFastBitSet2.prototype.array = function() {
if (this.arraySize === -1) {
var words = this.data;
var answer = new Array(this.size());
var pos = 0 | 0;
var c = words.length;
for (var k = 0; k < c; ++k) {
var w = words[k];
while (w != 0) {
var t = w & -w;
answer[pos++] = (k << 5) + (0, utils_1.hammingWeight)(t - 1 | 0);
w ^= t;
}
}
return answer;
} else {
var array = this.data;
var answer = new Array(this.arraySize);
for (var i = 0; i < this.arraySize; i++) {
answer[i] = array[i];
}
return answer;
}
};
SparseTypedFastBitSet2.prototype.forEach = function(fnc) {
if (this.arraySize === -1) {
var words = this.data;
var c = words.length;
for (var k = 0; k < c; ++k) {
var w = words[k];
while (w != 0) {
var t = w & -w;
fnc((k << 5) + (0, utils_1.hammingWeight)(t - 1) | 0);
w ^= t;
}
}
} else {
var array = this.data;
for (var i = 0; i < this.arraySize; i++) {
var v = array[i];
fnc(v);
if (v !== array[i]) {
i--;
}
}
}
};
SparseTypedFastBitSet2.prototype[Symbol.iterator] = function() {
var _a, _b;
if (this.arraySize === -1) {
var words_1 = this.data;
var c_1 = words_1.length;
var k_1 = 0;
var w_1 = words_1[k_1];
return _a = {}, _a[Symbol.iterator] = function() {
return this;
}, _a.next = function() {
while (k_1 < c_1) {
if (w_1 !== 0) {
var t = w_1 & -w_1;
var value = (k_1 << 5) + (0, utils_1.hammingWeight)(t - 1 | 0);
w_1 ^= t;
return { done: false, value };
} else {
k_1++;
if (k_1 < c_1) {
w_1 = words_1[k_1];
}
}
}
return { done: true, value: void 0 };
}, _a;
} else {
var array_1 = this.data;
var arraySize_1 = this.arraySize;
var i_1 = 0;
return _b = {}, _b[Symbol.iterator] = function() {
return this;
}, _b.next = function() {
if (i_1 < arraySize_1) {
var v = array_1[i_1];
var result = { done: false, value: v };
if (v !== array_1[i_1]) {
i_1--;
}
i_1++;
return result;
} else {
return { done: true, value: void 0 };
}
}, _b;
}
};
SparseTypedFastBitSet2.prototype.clone = function() {
var bitset = new SparseTypedFastBitSet2(
void 0,
new Uint32Array(this.data)
// Correction : pas d'annotation générique
);
bitset.arraySize = this.arraySize;
return bitset;
};
SparseTypedFastBitSet2.prototype.intersects = function(otherbitmap) {
var order = SparseTypedFastBitSet2.order(this, otherbitmap);
switch (order.type) {
case Type.BITSET: {
var firstWords = order.first.words;
var secondWords = order.second.words;
var newcount = Math.min(firstWords.length, secondWords.length);
for (var k = 0 | 0; k < newcount; ++k) {
if ((firstWords[k] & secondWords[k]) !== 0)
return true;
}
return false;
}
case Type.MIXED:
case Type.ARRAY: {
for (var i = 0; i < order.first.arraySize; i++) {
if (order.second.has(order.first.data[i])) {
return true;
}
}
return false;
}
}
};
SparseTypedFastBitSet2.prototype.intersection = function(otherbitmap) {
if (this.arraySize === -1) {
if (!(otherbitmap instanceof SparseTypedFastBitSet2) || otherbitmap.arraySize === -1) {
var words = this.data;
var otherWords = otherbitmap.words;
var newcount = Math.min(words.length, otherWords.length);
var k = 0 | 0;
for (; k + 7 < newcount; k += 8) {
words[k] &= otherWords[k];
words[k + 1] &= otherWords[k + 1];
words[k + 2] &= otherWords[k + 2];
words[k + 3] &= otherWords[k + 3];
words[k + 4] &= otherWords[k + 4];
words[k + 5] &= otherWords[k + 5];
words[k + 6] &= otherWords[k + 6];
words[k + 7] &= otherWords[k + 7];
}
for (; k < newcount; ++k) {
words[k] &= otherWords[k];
}
var c = words.length;
for (k = newcount; k < c; ++k) {
words[k] = 0;
}
return this;
} else {
var newWord = new Uint32Array(otherbitmap.data.length);
var otherArray = otherbitmap.data;
var newSize = 0;
for (var i = 0; i < otherbitmap.arraySize; i++) {
var index = otherArray[i];
if (this.has(index)) {
if (newSize > 0 && index > newWord[0]) {
newWord[newSize++] = newWord[0];
newWord[0] = index;
} else {
newWord[newSize++] = index;
}
}
}
this.data = newWord;
this.arraySize = newSize;
return this;
}
} else {
var array = this.data;
for (var i = 0; i < this.arraySize; i++) {
var v = array[i];
if (otherbitmap.has(v)) {
if (i > 0 && v > array[0]) {
array[i] = array[0];
array[0] = v;
}
} else {
array[i--] = array[--this.arraySize];
}
}
return this;
}
};
SparseTypedFastBitSet2.prototype.intersection_size = function(otherbitmap) {
var order = SparseTypedFastBitSet2.order(this, otherbitmap);
switch (order.type) {
case Type.BITSET: {
var words = order.first.words;
var otherWords = order.second.words;
var newcount = Math.min(words.length, otherWords.length);
var answer = 0 | 0;
for (var k = 0 | 0; k < newcount; ++k) {
answer += (0, utils_1.hammingWeight)(words[k] & otherWords[k]);
}
return answer;
}
case Type.MIXED:
case Type.ARRAY: {
var answer = 0;
var array = order.first.data;
for (var i = 0; i < order.first.arraySize; i++) {
if (order.second.has(array[i])) {
answer++;
}
}
return answer;
}
}
};
SparseTypedFastBitSet2.prototype.new_intersection = function(otherbitmap) {
var order = SparseTypedFastBitSet2.order(this, otherbitmap);
switch (order.type) {
case Type.BITSET: {
var words = order.first.words;
var otherWords = order.second.words;
var count = Math.min(words.length, otherWords.length);
var newWords = new Uint32Array(count);
var k = 0 | 0;
for (; k + 7 < count; k += 8) {
newWords[k] = words[k] & otherWords[k];
newWords[k + 1] = words[k + 1] & otherWords[k + 1];
newWords[k + 2] = words[k + 2] & otherWords[k + 2];
newWords[k + 3] = words[k + 3] & otherWords[k + 3];
newWords[k + 4] = words[k + 4] & otherWords[k + 4];
newWords[k + 5] = words[k + 5] & otherWords[k + 5];
newWords[k + 6] = words[k + 6] & otherWords[k + 6];
newWords[k + 7] = words[k + 7] & otherWords[k + 7];
}
for (; k < count; ++k) {
newWords[k] = words[k] & otherWords[k];
}
var answer = new SparseTypedFastBitSet2(void 0, newWords);
answer.arraySize = -1;
return answer;
}
case Type.MIXED:
case Type.ARRAY: {
var newArray = new Uint32Array(order.first.data.length);
var newSize = 0;
var array = order.first.data;
for (var i = 0; i < order.first.arraySize; i++) {
var index = array[i];
if (order.second.has(index)) {
if (newSize > 0 && index > newArray[0]) {
newArray[newSize++] = newArray[0];
newArray[0] = index;
} else {
newArray[newSize++] = index;
}
}
}
var answer = new SparseTypedFastBitSet2(void 0, newArray);
answer.arraySize = newSize;
return answer;
}
}
};
SparseTypedFastBitSet2.prototype.equals = function(otherbitmap) {
if (this === otherbitmap) {
return true;
}
var order = SparseTypedFastBitSet2.order(this, otherbitmap);
switch (order.type) {
case Type.BITSET: {
var words = this.words;
var otherWords = otherbitmap.words;
var mcount = Math.min(words.length, otherWords.length);
for (var k = 0 | 0; k < mcount; ++k) {
if (words[k] != otherWords[k])
return false;
}
if (words.length < otherWords.length) {
var c = otherWords.length;
for (var k = words.length; k < c; ++k) {
if (otherWords[k] != 0)
return false;
}
} else if (otherWords.length < words.length) {
var c = words.length;
for (var k = otherWords.length; k < c; ++k) {
if (words[k] != 0)
return false;
}
}
return true;
}
case Type.ARRAY:
case Type.MIXED: {
if (order.first.size() !== order.second.size()) {
return false;
}
var array = order.first.data;
for (var i = 0; i < order.first.arraySize; i++) {
if (!order.second.has(array[i])) {
return false;
}
}
return true;
}
}
};
SparseTypedFastBitSet2.prototype.difference = function(otherbitmap) {
if (this.arraySize === -1) {
if (!(otherbitmap instanceof SparseTypedFastBitSet2) || otherbitmap.arraySize === -1) {
var words = this.words;
var otherWords = otherbitmap.words;
var newcount = Math.min(words.length, otherWords.length);
var k = 0 | 0;
for (; k + 7 < newcount; k += 8) {
words[k] &= ~otherWords[k];
words[k + 1] &= ~otherWords[k + 1];
words[k + 2] &= ~otherWords[k + 2];
words[k + 3] &= ~otherWords[k + 3];
words[k + 4] &= ~otherWords[k + 4];
words[k + 5] &= ~otherWords[k + 5];
words[k + 6] &= ~otherWords[k + 6];
words[k + 7] &= ~otherWords[k + 7];
}
for (; k < newcount; ++k) {
words[k] &= ~otherWords[k];
}
return this;
} else {
var otherArray = otherbitmap.data;
for (var i = 0; i < otherbitmap.arraySize; i++) {
var index = otherArray[i];
if (this.has(index)) {
this.remove(index);
}
}
return this;
}
} else {
var array = this.data;
var findBiggest = false;
for (var i = 0; i < this.arraySize; i++) {
if (otherbitmap.has(array[i])) {
if (i === 0) {
findBiggest = true;
}
array[i--] = array[--this.arraySize];
}
}
if (findBiggest && this.arraySize > 1) {
var largest = array[0];
var largestIndex = 0;
for (var i = 1; i < this.arraySize; i++) {
if (array[i] > largest) {
largest = array[i];
largestIndex = i;
}
}
var current = array[0];
array[0] = array[largestIndex];
array[largestIndex] = current;
}
return this;
}
};
SparseTypedFastBitSet2.prototype.difference2 = function(otherbitmap) {
if (this.arraySize === -1 || !(otherbitmap instanceof SparseTypedFastBitSet2)) {
var words = this.words;
var mincount = Math.min(words.length, otherbitmap.words.length);
otherbitmap.resize((words.length << 5) - 1);
var otherWords = otherbitmap.words;
var k = 0 | 0;
for (; k + 7 < mincount; k += 8) {
otherWords[k] = words[k] & ~otherWords[k];
otherWords[k + 1] = words[k + 1] & ~otherWords[k + 1];
otherWords[k + 2] = words[k + 2] & ~otherWords[k + 2];
otherWords[k + 3] = words[k + 3] & ~otherWords[k + 3];
otherWords[k + 4] = words[k + 4] & ~otherWords[k + 4];
otherWords[k + 5] = words[k + 5] & ~otherWords[k + 5];
otherWords[k + 6] = words[k + 6] & ~otherWords[k + 6];
otherWords[k + 7] = words[k + 7] & ~otherWords[k + 7];
}
for (; k < mincount; ++k) {
otherWords[k] = words[k] & ~otherWords[k];
}
for (; k < words.length; ++k) {
otherWords[k] = words[k];
}
otherWords.fill(0, k);
return otherbitmap;
} else {
var array = new Uint32Array(this.data);
var arraySize = this.arraySize;
var findBiggest = false;
for (var i = 0; i < arraySize; i++) {
if (otherbitmap.has(array[i])) {
if (i === 0) {
findBiggest = true;
}
array[i--] = array[--arraySize];
}
}
if (findBiggest && arraySize > 1) {
var largest = array[0];
var largestIndex = 0;
for (var i = 1; i < arraySize; i++) {
if (array[i] > largest) {
largest = array[i];
largestIndex = i;
}
}
var current = array[0];
array[0] = array[largestIndex];
array[largestIndex] = current;
}
otherbitmap.data = array;
otherbitmap.arraySize = arraySize;
return otherbitmap;
}
};
SparseTypedFastBitSet2.prototype.new_difference = function(otherbitmap) {
return this.clone().difference(otherbitmap);
};
SparseTypedFastBitSet2.prototype.difference_size = function(otherbitmap) {
if (this.arraySize === -1) {
if (!(otherbitmap instanceof SparseTypedFastBitSet2) || otherbitmap.arraySize === -1) {
var words = this.words;
var otherWords = otherbitmap.words;
var newcount = Math.min(words.length, otherWords.length);
var answer = 0 | 0;
var k = 0 | 0;
for (; k < newcount; ++k) {
answer += (0, utils_1.hammingWeight)(words[k] & ~otherWords[k]);
}
var c = words.length;
for (; k < c; ++k) {
answer += (0, utils_1.hammingWeight)(words[k]);
}
return answer;
} else {
var answer = this.size();
var otherArray = otherbitmap.data;
for (var i = 0; i < otherbitmap.arraySize; i++) {
var index = otherArray[i];
if (this.has(index)) {
answer--;
}
}
return answer;
}
} else {
var answer = this.arraySize;
var array = this.data;
for (var i = 0; i < this.arraySize; i++) {
if (otherbitmap.has(array[i])) {
answer--;
}
}
return answer;
}
};
SparseTypedFastBitSet2.prototype.change = function(otherbitmap) {
if (this.arraySize === -1) {
if (!(otherbitmap instanceof SparseTypedFastBitSet2) || otherbitmap.arraySize === -1) {
var otherWords = otherbitmap.words;
var mincount = Math.min(this.words.length, otherWords.length);
this.resize((otherWords.length << 5) - 1);
var words = this.words;
var k = 0 | 0;
for (; k + 7 < mincount; k += 8) {
words[k] ^= otherWords[k];
words[k + 1] ^= otherWords[k + 1];
words[k + 2] ^= otherWords[k + 2];
words[k + 3] ^= otherWords[k + 3];
words[k + 4] ^= otherWords[k + 4];
words[k + 5] ^= otherWords[k + 5];
words[k + 6] ^= otherWords[k + 6];
words[k + 7] ^= otherWords[k + 7];
}
for (; k < mincount; ++k) {
words[k] ^= otherWords[k];
}
for (; k < otherWords.length; ++k) {
words[k] = otherWords[k];
}
return this;
} else if (otherbitmap.arraySize > 0) {
var otherArray = otherbitmap.data;
this.resize(otherArray[0]);
var words = this.words;
for (var i = 0; i < otherbitmap.arraySize; i++) {
var index = otherArray[i];
if ((words[index >>> 5] & 1 << index) !== 0) {
words[index >>> 5] &= ~(1 << index);
} else {
words[index >>> 5] |= 1 << index;
}
}
return this;
} else {
return this;
}
} else {
if (!(otherbitmap instanceof SparseTypedFastBitSet2) || otherbitmap.arraySize === -1) {
var words = new Uint32Array(Math.max(otherbitmap.words.length, this.arraySize > 0 ? this.data[0] << 5 + 32 : 0));
words.set(otherbitmap.words);
var array = this.data;
for (var i = 0; i < this.arraySize; i++) {
var index = array[i];
if ((words[index >>> 5] & 1 << index) !== 0) {
words[index >>> 5] &= ~(1 << index);
} else {
words[index >>> 5] |= 1 << index;
}
}
this.data = words;
this.arraySize = -1;
} else {
var otherArray = otherbitmap.data;
for (var i = 0; i < otherbitmap.arraySize; i++) {
var index = otherArray[i];
if (this.has(index)) {
this.remove(index);
} else {
this.add(index);
}
}
}
return this;
}
};
SparseTypedFastBitSet2.prototype.new_change = function(otherbitmap) {
var order = SparseTypedFastBitSet2.order(this, otherbitmap);
switch (order.type) {
case Type.BITSET: {
var words = this.words;
var otherWords = otherbitmap.words;
var count = Math.max(words.length, otherWords.length);
var answer = new SparseTypedFastBitSet2(void 0, new Uint32Array(count));
answer.arraySize = -1;
var mcount = Math.min(words.length, otherWords.length);
var k = 0;
for (; k + 7 < mcount; k += 8) {
answer.words[k] = words[k] ^ otherWords[k];
answer.words[k + 1] = words[k + 1] ^ otherWords[k + 1];
answer.words[k + 2] = words[k + 2] ^ otherWords[k + 2];
answer.words[k + 3] = words[k + 3] ^ otherWords[k + 3];
answer.words[k + 4] = words[k + 4] ^ otherWords[k + 4];
answer.words[k + 5] = words[k + 5] ^ otherWords[k + 5];
answer.words[k + 6] = words[k + 6] ^ otherWords[k + 6];
answer.words[k + 7] = words[k + 7] ^ otherWords[k + 7];
}
for (; k < mcount; ++k) {
answer.words[k] = words[k] ^ otherWords[k];
}
var c = words.length;
for (k = mcount; k < c; ++k) {
answer.words[k] = words[k];
}
var c2 = otherWords.length;
for (k = mcount; k < c2; ++k) {
answer.words[k] = otherWords[k];
}
return answer;
}
case Type.MIXED: {
var words = new Uint32Array(Math.max(order.second.words.length, order.first.arraySize > 0 ? order.first.data[0] + 32 << 5 : 0));
words.set(order.second.words);
var array = order.first.data;
for (var i = 0; i < order.first.arraySize; i++) {
var index = array[i];
if ((words[index >>> 5] & 1 << index) !== 0) {
words[index >>> 5] &= ~(1 << index);
} else {
words[index >>> 5] |= 1 << index;
}
}
var answer = new SparseTypedFastBitSet2(void 0, words);
answer.arraySize = -1;
return answer;
}
case Type.ARRAY: {
var newArray = new Uint32Array(order.first.data.length + order.second.data.length);
newArray.set(order.second.data);
var newSize = order.second.arraySize;
var array = order.first.data;
for (var i = 0; i < order.first.arraySize; i++) {
var index = array[i];
var offset = newArray.indexOf(index);
if (offset !== -1 && offset < newSize) {
newArray[offset] = newArray[--newSize];
} else {
newArray[newSize++] = index;
}
}
if (newSize > 1) {
var largest = newArray[0];
var largestIndex = 0;
for (var i = 1; i < newSize; i++) {
if (newArray[i] > largest) {
largest = newArray[i];
largestIndex = i;
}
}
var current = newArray[0];
newArray[0] = newArray[largestIndex];
newArray[largestIndex] = current;
}
var answer = new SparseTypedFastBitSet2(void 0, newArray);
answer.arraySize = newSize;
return answer;
}
}
};
SparseTypedFastBitSet2.prototype.change_size = function(otherbitmap) {
var order = SparseTypedFastBitSet2.order(this, otherbitmap);
switch (order.type) {
case Type.BITSET: {
var words = this.words;
var otherWords = otherbitmap.words;
var mincount = Math.min(words.length, otherWords.length);
var answer = 0 | 0;
var k = 0 | 0;
for (; k < mincount; ++k) {
answer += (0, utils_1.hammingWeight)(words[k] ^ otherWords[k]);
}
var longer = words.length > otherWords.length ? this : otherbitmap;
var c = longer.words.length;
for (; k < c; ++k) {
answer += (0, utils_1.hammingWeight)(longer.words[k]);
}
return answer;
}
case Type.MIXED: {
var array = order.first.data;
var answer = order.second.size();
for (var i = 0; i < order.first.arraySize; i++) {
var index = array[i];
if (order.second.has(index)) {
answer--;
} else {
answer++;
}
}
return answer;
}
case Type.ARRAY: {
var answer = order.second.arraySize;
var array = order.first.data;
for (var i = 0; i < order.first.arraySize; i++) {
var index = array[i];
if (order.second.has(index)) {
answer--;
} else {
answer++;
}
}
return answer;
}
}
};
SparseTypedFastBitSet2.prototype.toString = function() {
return "{" + this.array().join(",") + "}";
};
SparseTypedFastBitSet2.prototype.union = function(otherbitmap) {
if (!(otherbitmap instanceof SparseTypedFastBitSet2) || otherbitmap.arraySize === -1) {
if (this.arraySize !== -1) {
this.data = this.toBitset();
this.arraySize = -1;
}
var words = this.data;
var otherWords = otherbitmap.words;
var mcount = Math.min(words.length, otherWords.length);
var k = 0 | 0;
for (; k + 7 < mcount; k += 8) {
words[k] |= otherWords[k];
words[k + 1] |= otherWords[k + 1];
words[k + 2] |= otherWords[k + 2];
words[k + 3] |= otherWords[k + 3];
words[k + 4] |= otherWords[k + 4];
words[k + 5] |= otherWords[k + 5];
words[k + 6] |= otherWords[k + 6];
words[k + 7] |= otherWords[k + 7];
}
for (; k < mcount; ++k) {
words[k] |= otherWords[k];
}
if (words.length < otherWords.length) {
this.resize((otherWords.length << 5) - 1);
words = this.data;
var c = otherWords.length;
for (k = mcount; k < c; ++k) {
words[k] = otherWords[k];
}
}
return this;
} else {
var otherArray = otherbitmap.data;
for (var i = 0; i < otherbitmap.arraySize; i++) {
var index = otherArray[i];
this.add(index);
}
return this;
}
};
SparseTypedFastBitSet2.prototype.new_union = function(otherbitmap) {
if (!(otherbitmap instanceof SparseTypedFastBitSet2) || otherbitmap.arraySize === -1) {
var words = this.data;
if (this.arraySize !== -1) {
words = this.toBitset();
}
var otherWords = otherbitmap.words;
var count = Math.max(words.length, otherWords.length);
var answer = new SparseTypedFastBitSet2(void 0, new Uint32Array(count));
answer.arraySize = -1;
var mcount = Math.min(words.length, otherWords.length);
for (var k = 0; k < mcount; ++k) {
answer.words[k] = words[k] | otherWords[k];
}
var c = words.length;
for (var k = mcount; k < c; ++k) {
answer.words[k] = words[k];
}
var c2 = otherWords.length;
for (var k = mcount; k < c2; ++k) {
answer.words[k] = otherWords[k];
}
return answer;
} else {
var answer = this.clone();
var otherArray = otherbitmap.data;
for (var i = 0; i < otherbitmap.arraySize; i++) {
var index = otherArray[i];
answer.add(index);
}
return answer;
}
};
SparseTypedFastBitSet2.prototype.union_size = function(otherbitmap) {
var order = SparseTypedFastBitSet2.order(this, otherbitmap);
switch (order.type) {
case Type.BITSET: {
var words = order.first.words;
var otherWords = order.second.words;
var mcount = Math.min(words.length, otherWords.length);
var answer = 0 | 0;
for (var k = 0 | 0; k < mcount; ++k) {
answer += (0, utils_1.hammingWeight)(words[k] | otherWords[k]);
}
if (words.length < otherWords.length) {
var c = otherWords.length;
for (var k = words.l