UNPKG

@graphty/algorithms

Version:

Graph algorithms library for browser environments implemented in TypeScript

1,459 lines 346 kB
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