Projektstart
This commit is contained in:
21
backend/node_modules/mnemonist/LICENSE.txt
generated
vendored
Normal file
21
backend/node_modules/mnemonist/LICENSE.txt
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Guillaume Plique (Yomguithereal)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
112
backend/node_modules/mnemonist/README.md
generated
vendored
Normal file
112
backend/node_modules/mnemonist/README.md
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
[](https://github.com/Yomguithereal/mnemonist/actions)
|
||||
|
||||
# Mnemonist
|
||||
|
||||
Mnemonist is a curated collection of data structures for the JavaScript language.
|
||||
|
||||
It gathers classic data structures (think heap, trie etc.) as well as more exotic ones such as Buckhard-Keller trees etc.
|
||||
|
||||
It strives at being:
|
||||
|
||||
* As performant as possible for a high-level language.
|
||||
* Completely modular (don't need to import the whole library just to use a simple heap).
|
||||
* Simple & straightforward to use and consistent with JavaScript standard objects' API.
|
||||
* Completely typed and comfortably usable with Typescript.
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
npm install --save mnemonist
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
Full documentation for the library can be found [here](https://yomguithereal.github.io/mnemonist).
|
||||
|
||||
**Classics**
|
||||
|
||||
* [Heap](https://yomguithereal.github.io/mnemonist/heap)
|
||||
* [Linked List](https://yomguithereal.github.io/mnemonist/linked-list)
|
||||
* [LRUCache](https://yomguithereal.github.io/mnemonist/lru-cache), [LRUMap](https://yomguithereal.github.io/mnemonist/lru-map)
|
||||
* [MultiMap](https://yomguithereal.github.io/mnemonist/multi-map)
|
||||
* [MultiSet](https://yomguithereal.github.io/mnemonist/multi-set)
|
||||
* [Queue](https://yomguithereal.github.io/mnemonist/queue)
|
||||
* [Set (helpers)](https://yomguithereal.github.io/mnemonist/set)
|
||||
* [Stack](https://yomguithereal.github.io/mnemonist/stack)
|
||||
* [Trie](https://yomguithereal.github.io/mnemonist/trie)
|
||||
* [TrieMap](https://yomguithereal.github.io/mnemonist/trie-map)
|
||||
|
||||
**Low-level & structures for very specific use cases**
|
||||
|
||||
* [Circular Buffer](https://yomguithereal.github.io/mnemonist/circular-buffer)
|
||||
* [Fixed Deque](https://yomguithereal.github.io/mnemonist/fixed-deque)
|
||||
* [Fibonacci Heap](https://yomguithereal.github.io/mnemonist/fibonacci-heap)
|
||||
* [Fixed Reverse Heap](https://yomguithereal.github.io/mnemonist/fixed-reverse-heap)
|
||||
* [Fixed Stack](https://yomguithereal.github.io/mnemonist/fixed-stack)
|
||||
* [Hashed Array Tree](https://yomguithereal.github.io/mnemonist/hashed-array-tree)
|
||||
* [Static DisjointSet](https://yomguithereal.github.io/mnemonist/static-disjoint-set)
|
||||
* [SparseQueueSet](https://yomguithereal.github.io/mnemonist/sparse-queue-set)
|
||||
* [SparseMap](https://yomguithereal.github.io/mnemonist/sparse-map)
|
||||
* [SparseSet](https://yomguithereal.github.io/mnemonist/sparse-set)
|
||||
* [Suffix Array](https://yomguithereal.github.io/mnemonist/suffix-array)
|
||||
* [Generalized Suffix Array](https://yomguithereal.github.io/mnemonist/generalized-suffix-array)
|
||||
* [Vector](https://yomguithereal.github.io/mnemonist/vector)
|
||||
|
||||
**Information retrieval & Natural language processing**
|
||||
|
||||
* [Fuzzy Map](https://yomguithereal.github.io/mnemonist/fuzzy-map)
|
||||
* [Fuzzy MultiMap](https://yomguithereal.github.io/mnemonist/fuzzy-multi-map)
|
||||
* [Inverted Index](https://yomguithereal.github.io/mnemonist/inverted-index)
|
||||
* [Passjoin Index](https://yomguithereal.github.io/mnemonist/passjoin-index)
|
||||
* [SymSpell](https://yomguithereal.github.io/mnemonist/symspell)
|
||||
|
||||
**Space & time indexation**
|
||||
|
||||
* [Static IntervalTree](https://yomguithereal.github.io/mnemonist/static-interval-tree)
|
||||
* [KD-Tree](https://yomguithereal.github.io/mnemonist/kd-tree)
|
||||
|
||||
**Metric space indexation**
|
||||
|
||||
* [Burkhard-Keller Tree](https://yomguithereal.github.io/mnemonist/bk-tree)
|
||||
* [Vantage Point Tree](https://yomguithereal.github.io/mnemonist/vp-tree)
|
||||
|
||||
**Probabilistic & succinct data structures**
|
||||
|
||||
* [BitSet](https://yomguithereal.github.io/mnemonist/bit-set)
|
||||
* [BitVector](https://yomguithereal.github.io/mnemonist/bit-vector)
|
||||
* [Bloom Filter](https://yomguithereal.github.io/mnemonist/bloom-filter)
|
||||
|
||||
**Utility classes**
|
||||
|
||||
* [BiMap](https://yomguithereal.github.io/mnemonist/bi-map)
|
||||
* [DefaultMap](https://yomguithereal.github.io/mnemonist/default-map)
|
||||
* [DefaultWeakMap](https://yomguithereal.github.io/mnemonist/default-weak-map)
|
||||
|
||||
---
|
||||
|
||||
Note that this list does not include a `Graph` data structure, whose implementation is usually far too complex for the scope of this library.
|
||||
|
||||
However, we advise the reader to take a look at the [`graphology`](https://graphology.github.io/) library instead.
|
||||
|
||||
Don't find the data structure you need? Maybe we can work it out [together](https://github.com/Yomguithereal/mnemonist/issues).
|
||||
|
||||
## Contribution
|
||||
|
||||
Contributions are obviously welcome. Be sure to lint the code & add relevant unit tests.
|
||||
|
||||
```
|
||||
# Installing
|
||||
git clone git@github.com:Yomguithereal/mnemonist.git
|
||||
cd mnemonist
|
||||
npm install
|
||||
|
||||
# Linting
|
||||
npm run lint
|
||||
|
||||
# Running the unit tests
|
||||
npm test
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE.txt)
|
||||
46
backend/node_modules/mnemonist/bi-map.d.ts
generated
vendored
Normal file
46
backend/node_modules/mnemonist/bi-map.d.ts
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Mnemonist BiMap Typings
|
||||
* ========================
|
||||
*/
|
||||
export class InverseMap<K, V> implements Iterable<[K, V]> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
inverse: BiMap<V, K>;
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
set(key: K, value: V): this;
|
||||
delete(key: K): boolean;
|
||||
has(key: K): boolean;
|
||||
get(key: K): V | undefined;
|
||||
forEach(callback: (value: V, key: K, map: this) => void, scope?: any): void;
|
||||
keys(): IterableIterator<K>;
|
||||
values(): IterableIterator<V>;
|
||||
entries(): IterableIterator<[K, V]>;
|
||||
[Symbol.iterator](): IterableIterator<[K, V]>;
|
||||
inspect(): any;
|
||||
}
|
||||
|
||||
export default class BiMap<K, V> implements Iterable<[K, V]> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
inverse: InverseMap<V, K>;
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
set(key: K, value: V): this;
|
||||
delete(key: K): boolean;
|
||||
has(key: K): boolean;
|
||||
get(key: K): V | undefined;
|
||||
forEach(callback: (value: V, key: K, map: this) => void, scope?: any): void;
|
||||
keys(): IterableIterator<K>;
|
||||
values(): IterableIterator<V>;
|
||||
entries(): IterableIterator<[K, V]>;
|
||||
[Symbol.iterator](): IterableIterator<[K, V]>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I, J>(iterable: Iterable<[I, J]> | {[key: string]: J}): BiMap<I, J>;
|
||||
}
|
||||
195
backend/node_modules/mnemonist/bi-map.js
generated
vendored
Normal file
195
backend/node_modules/mnemonist/bi-map.js
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
/**
|
||||
* Mnemonist BiMap
|
||||
* ================
|
||||
*
|
||||
* JavaScript implementation of a BiMap.
|
||||
*/
|
||||
var forEach = require('obliterator/foreach');
|
||||
|
||||
/**
|
||||
* Inverse Map.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function InverseMap(original) {
|
||||
|
||||
this.size = 0;
|
||||
this.items = new Map();
|
||||
this.inverse = original;
|
||||
}
|
||||
|
||||
/**
|
||||
* BiMap.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function BiMap() {
|
||||
|
||||
this.size = 0;
|
||||
this.items = new Map();
|
||||
this.inverse = new InverseMap(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the map.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
function clear() {
|
||||
this.size = 0;
|
||||
this.items.clear();
|
||||
this.inverse.items.clear();
|
||||
}
|
||||
|
||||
BiMap.prototype.clear = clear;
|
||||
InverseMap.prototype.clear = clear;
|
||||
|
||||
/**
|
||||
* Method used to set a relation.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @param {any} value - Value.
|
||||
* @return {BiMap|InverseMap}
|
||||
*/
|
||||
function set(key, value) {
|
||||
|
||||
// First we need to attempt to see if the relation is not flawed
|
||||
if (this.items.has(key)) {
|
||||
var currentValue = this.items.get(key);
|
||||
|
||||
// The relation already exists, we do nothing
|
||||
if (currentValue === value)
|
||||
return this;
|
||||
else
|
||||
this.inverse.items.delete(currentValue);
|
||||
}
|
||||
|
||||
if (this.inverse.items.has(value)) {
|
||||
var currentKey = this.inverse.items.get(value);
|
||||
|
||||
if (currentKey === key)
|
||||
return this;
|
||||
else
|
||||
this.items.delete(currentKey);
|
||||
}
|
||||
|
||||
// Here we actually add the relation
|
||||
this.items.set(key, value);
|
||||
this.inverse.items.set(value, key);
|
||||
|
||||
// Size
|
||||
this.size = this.items.size;
|
||||
this.inverse.size = this.inverse.items.size;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
BiMap.prototype.set = set;
|
||||
InverseMap.prototype.set = set;
|
||||
|
||||
/**
|
||||
* Method used to delete a relation.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @return {boolean}
|
||||
*/
|
||||
function del(key) {
|
||||
if (this.items.has(key)) {
|
||||
var currentValue = this.items.get(key);
|
||||
|
||||
this.items.delete(key);
|
||||
this.inverse.items.delete(currentValue);
|
||||
|
||||
// Size
|
||||
this.size = this.items.size;
|
||||
this.inverse.size = this.inverse.items.size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BiMap.prototype.delete = del;
|
||||
InverseMap.prototype.delete = del;
|
||||
|
||||
/**
|
||||
* Mapping some Map prototype function unto our two classes.
|
||||
*/
|
||||
var METHODS = ['has', 'get', 'forEach', 'keys', 'values', 'entries'];
|
||||
|
||||
METHODS.forEach(function(name) {
|
||||
BiMap.prototype[name] = InverseMap.prototype[name] = function() {
|
||||
return Map.prototype[name].apply(this.items, arguments);
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Attaching the #.values method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined') {
|
||||
BiMap.prototype[Symbol.iterator] = BiMap.prototype.entries;
|
||||
InverseMap.prototype[Symbol.iterator] = InverseMap.prototype.entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
BiMap.prototype.inspect = function() {
|
||||
var dummy = {
|
||||
left: this.items,
|
||||
right: this.inverse.items
|
||||
};
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(dummy, 'constructor', {
|
||||
value: BiMap,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return dummy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
BiMap.prototype[Symbol.for('nodejs.util.inspect.custom')] = BiMap.prototype.inspect;
|
||||
|
||||
InverseMap.prototype.inspect = function() {
|
||||
var dummy = {
|
||||
left: this.inverse.items,
|
||||
right: this.items
|
||||
};
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(dummy, 'constructor', {
|
||||
value: InverseMap,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return dummy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
InverseMap.prototype[Symbol.for('nodejs.util.inspect.custom')] = InverseMap.prototype.inspect;
|
||||
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a bimap.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @return {BiMap}
|
||||
*/
|
||||
BiMap.from = function(iterable) {
|
||||
var bimap = new BiMap();
|
||||
|
||||
forEach(iterable, function(value, key) {
|
||||
bimap.set(key, value);
|
||||
});
|
||||
|
||||
return bimap;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = BiMap;
|
||||
29
backend/node_modules/mnemonist/bit-set.d.ts
generated
vendored
Normal file
29
backend/node_modules/mnemonist/bit-set.d.ts
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Mnemonist BitSet Typings
|
||||
* =========================
|
||||
*/
|
||||
export default class BitSet implements Iterable<number> {
|
||||
|
||||
// Members
|
||||
length: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(length: number);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
set(index: number, value?: boolean | number): void;
|
||||
reset(index: number, value: boolean | number): void;
|
||||
flip(index: number, value: boolean | number): void;
|
||||
get(index: number): number;
|
||||
test(index: number): boolean;
|
||||
rank(r: number): number;
|
||||
select(r: number): number;
|
||||
forEach(callback: (index: number, value: number, set: this) => void, scope?: any): void;
|
||||
values(): IterableIterator<number>;
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
inspect(): any;
|
||||
toJSON(): Array<number>;
|
||||
}
|
||||
379
backend/node_modules/mnemonist/bit-set.js
generated
vendored
Normal file
379
backend/node_modules/mnemonist/bit-set.js
generated
vendored
Normal file
@@ -0,0 +1,379 @@
|
||||
/**
|
||||
* Mnemonist BitSet
|
||||
* =================
|
||||
*
|
||||
* JavaScript implementation of a fixed-size BitSet based upon a Uint32Array.
|
||||
*
|
||||
* Notes:
|
||||
* - (i >> 5) is the same as ((i / 32) | 0)
|
||||
* - (i & 0x0000001f) is the same as (i % 32)
|
||||
* - I could use a Float64Array to store more in less blocks but I would lose
|
||||
* the benefits of byte comparison to keep track of size without popcounts.
|
||||
*/
|
||||
var Iterator = require('obliterator/iterator'),
|
||||
bitwise = require('./utils/bitwise.js');
|
||||
|
||||
/**
|
||||
* BitSet.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function BitSet(length) {
|
||||
|
||||
// Properties
|
||||
this.length = length;
|
||||
this.clear();
|
||||
|
||||
// Methods
|
||||
|
||||
// Statics
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the bit set.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
BitSet.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
this.array = new Uint32Array(Math.ceil(this.length / 32));
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set the given bit's value.
|
||||
*
|
||||
* @param {number} index - Target bit index.
|
||||
* @param {number} value - Value to set.
|
||||
* @return {BitSet}
|
||||
*/
|
||||
BitSet.prototype.set = function(index, value) {
|
||||
var byteIndex = index >> 5,
|
||||
pos = index & 0x0000001f,
|
||||
oldBytes = this.array[byteIndex],
|
||||
newBytes;
|
||||
|
||||
if (value === 0 || value === false)
|
||||
newBytes = this.array[byteIndex] &= ~(1 << pos);
|
||||
else
|
||||
newBytes = this.array[byteIndex] |= (1 << pos);
|
||||
|
||||
// The operands of all bitwise operators are converted to *signed* 32-bit integers.
|
||||
// Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Signed_32-bit_integers
|
||||
// Shifting by 31 changes the sign (i.e. 1 << 31 = -2147483648).
|
||||
// Therefore, get unsigned representation by applying '>>> 0'.
|
||||
newBytes = newBytes >>> 0;
|
||||
|
||||
// Updating size
|
||||
if (newBytes > oldBytes)
|
||||
this.size++;
|
||||
else if (newBytes < oldBytes)
|
||||
this.size--;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to reset the given bit's value.
|
||||
*
|
||||
* @param {number} index - Target bit index.
|
||||
* @return {BitSet}
|
||||
*/
|
||||
BitSet.prototype.reset = function(index) {
|
||||
var byteIndex = index >> 5,
|
||||
pos = index & 0x0000001f,
|
||||
oldBytes = this.array[byteIndex],
|
||||
newBytes;
|
||||
|
||||
newBytes = this.array[byteIndex] &= ~(1 << pos);
|
||||
|
||||
// Updating size
|
||||
if (newBytes < oldBytes)
|
||||
this.size--;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to flip the value of the given bit.
|
||||
*
|
||||
* @param {number} index - Target bit index.
|
||||
* @return {BitSet}
|
||||
*/
|
||||
BitSet.prototype.flip = function(index) {
|
||||
var byteIndex = index >> 5,
|
||||
pos = index & 0x0000001f,
|
||||
oldBytes = this.array[byteIndex];
|
||||
|
||||
var newBytes = this.array[byteIndex] ^= (1 << pos);
|
||||
|
||||
// Get unsigned representation.
|
||||
newBytes = newBytes >>> 0;
|
||||
|
||||
// Updating size
|
||||
if (newBytes > oldBytes)
|
||||
this.size++;
|
||||
else if (newBytes < oldBytes)
|
||||
this.size--;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the given bit's value.
|
||||
*
|
||||
* @param {number} index - Target bit index.
|
||||
* @return {number}
|
||||
*/
|
||||
BitSet.prototype.get = function(index) {
|
||||
var byteIndex = index >> 5,
|
||||
pos = index & 0x0000001f;
|
||||
|
||||
return (this.array[byteIndex] >> pos) & 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to test the given bit's value.
|
||||
*
|
||||
* @param {number} index - Target bit index.
|
||||
* @return {BitSet}
|
||||
*/
|
||||
BitSet.prototype.test = function(index) {
|
||||
return Boolean(this.get(index));
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to return the number of 1 from the beginning of the set up to
|
||||
* the ith index.
|
||||
*
|
||||
* @param {number} i - Ith index (cannot be > length).
|
||||
* @return {number}
|
||||
*/
|
||||
BitSet.prototype.rank = function(i) {
|
||||
if (this.size === 0)
|
||||
return 0;
|
||||
|
||||
var byteIndex = i >> 5,
|
||||
pos = i & 0x0000001f,
|
||||
r = 0;
|
||||
|
||||
// Accessing the bytes before the last one
|
||||
for (var j = 0; j < byteIndex; j++)
|
||||
r += bitwise.table8Popcount(this.array[j]);
|
||||
|
||||
// Handling masked last byte
|
||||
var maskedByte = this.array[byteIndex] & ((1 << pos) - 1);
|
||||
|
||||
r += bitwise.table8Popcount(maskedByte);
|
||||
|
||||
return r;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to return the position of the rth 1 in the set or -1 if the
|
||||
* set is empty.
|
||||
*
|
||||
* Note: usually select is implemented using binary search over rank but I
|
||||
* tend to think the following linear implementation is faster since here
|
||||
* rank is O(n) anyway.
|
||||
*
|
||||
* @param {number} r - Rth 1 to select (should be < length).
|
||||
* @return {number}
|
||||
*/
|
||||
BitSet.prototype.select = function(r) {
|
||||
if (this.size === 0)
|
||||
return -1;
|
||||
|
||||
// TODO: throw?
|
||||
if (r >= this.length)
|
||||
return -1;
|
||||
|
||||
var byte,
|
||||
b = 32,
|
||||
p = 0,
|
||||
c = 0;
|
||||
|
||||
for (var i = 0, l = this.array.length; i < l; i++) {
|
||||
byte = this.array[i];
|
||||
|
||||
// The byte is empty, let's continue
|
||||
if (byte === 0)
|
||||
continue;
|
||||
|
||||
// TODO: This branching might not be useful here
|
||||
if (i === l - 1)
|
||||
b = this.length % 32 || 32;
|
||||
|
||||
// TODO: popcount should speed things up here
|
||||
|
||||
for (var j = 0; j < b; j++, p++) {
|
||||
c += (byte >> j) & 1;
|
||||
|
||||
if (c === r)
|
||||
return p;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the bit set's values.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
BitSet.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
var length = this.length,
|
||||
byte,
|
||||
bit,
|
||||
b = 32;
|
||||
|
||||
for (var i = 0, l = this.array.length; i < l; i++) {
|
||||
byte = this.array[i];
|
||||
|
||||
if (i === l - 1)
|
||||
b = length % 32 || 32;
|
||||
|
||||
for (var j = 0; j < b; j++) {
|
||||
bit = (byte >> j) & 1;
|
||||
|
||||
callback.call(scope, bit, i * 32 + j);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a set's values.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
BitSet.prototype.values = function() {
|
||||
var length = this.length,
|
||||
inner = false,
|
||||
byte,
|
||||
bit,
|
||||
array = this.array,
|
||||
l = array.length,
|
||||
i = 0,
|
||||
j = -1,
|
||||
b = 32;
|
||||
|
||||
return new Iterator(function next() {
|
||||
if (!inner) {
|
||||
|
||||
if (i >= l)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
if (i === l - 1)
|
||||
b = length % 32 || 32;
|
||||
|
||||
byte = array[i++];
|
||||
inner = true;
|
||||
j = -1;
|
||||
}
|
||||
|
||||
j++;
|
||||
|
||||
if (j >= b) {
|
||||
inner = false;
|
||||
return next();
|
||||
}
|
||||
|
||||
bit = (byte >> j) & 1;
|
||||
|
||||
return {
|
||||
value: bit
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a set's entries.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
BitSet.prototype.entries = function() {
|
||||
var length = this.length,
|
||||
inner = false,
|
||||
byte,
|
||||
bit,
|
||||
array = this.array,
|
||||
index,
|
||||
l = array.length,
|
||||
i = 0,
|
||||
j = -1,
|
||||
b = 32;
|
||||
|
||||
return new Iterator(function next() {
|
||||
if (!inner) {
|
||||
|
||||
if (i >= l)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
if (i === l - 1)
|
||||
b = length % 32 || 32;
|
||||
|
||||
byte = array[i++];
|
||||
inner = true;
|
||||
j = -1;
|
||||
}
|
||||
|
||||
j++;
|
||||
index = (~-i) * 32 + j;
|
||||
|
||||
if (j >= b) {
|
||||
inner = false;
|
||||
return next();
|
||||
}
|
||||
|
||||
bit = (byte >> j) & 1;
|
||||
|
||||
return {
|
||||
value: [index, bit]
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.values method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
BitSet.prototype[Symbol.iterator] = BitSet.prototype.values;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
BitSet.prototype.inspect = function() {
|
||||
var proxy = new Uint8Array(this.length);
|
||||
|
||||
this.forEach(function(bit, i) {
|
||||
proxy[i] = bit;
|
||||
});
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: BitSet,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
BitSet.prototype[Symbol.for('nodejs.util.inspect.custom')] = BitSet.prototype.inspect;
|
||||
|
||||
BitSet.prototype.toJSON = function() {
|
||||
return Array.from(this.array);
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = BitSet;
|
||||
42
backend/node_modules/mnemonist/bit-vector.d.ts
generated
vendored
Normal file
42
backend/node_modules/mnemonist/bit-vector.d.ts
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Mnemonist BitVector Typings
|
||||
* ============================
|
||||
*/
|
||||
type BitVectorOptions = {
|
||||
initialLength?: number;
|
||||
initialCapacity?: number;
|
||||
policy?: (capacity: number) => number;
|
||||
}
|
||||
|
||||
export default class BitVector implements Iterable<number> {
|
||||
|
||||
// Members
|
||||
capacity: number;
|
||||
length: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(length: number);
|
||||
constructor(options: BitVectorOptions);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
set(index: number, value?: boolean | number): this;
|
||||
reset(index: number, value: boolean | number): void;
|
||||
flip(index: number, value: boolean | number): void;
|
||||
reallocate(capacity: number): this;
|
||||
grow(capacity?: number): this;
|
||||
resize(length: number): this;
|
||||
push(value: boolean | number): number;
|
||||
pop(): number | undefined;
|
||||
get(index: number): number;
|
||||
test(index: number): boolean;
|
||||
rank(r: number): number;
|
||||
select(r: number): number;
|
||||
forEach(callback: (index: number, value: number, set: this) => void, scope?: any): void;
|
||||
values(): IterableIterator<number>;
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
inspect(): any;
|
||||
toJSON(): Array<number>;
|
||||
}
|
||||
550
backend/node_modules/mnemonist/bit-vector.js
generated
vendored
Normal file
550
backend/node_modules/mnemonist/bit-vector.js
generated
vendored
Normal file
@@ -0,0 +1,550 @@
|
||||
/**
|
||||
* Mnemonist BitVector
|
||||
* ====================
|
||||
*
|
||||
* JavaScript implementation of a dynamic BitSet based upon a Uint32Array.
|
||||
*
|
||||
* Notes:
|
||||
* - (i >> 5) is the same as ((i / 32) | 0)
|
||||
* - (i & 0x0000001f) is the same as (i % 32)
|
||||
* - I could use a Float64Array to store more in less blocks but I would lose
|
||||
* the benefits of byte comparison to keep track of size without popcounts.
|
||||
*/
|
||||
var Iterator = require('obliterator/iterator'),
|
||||
bitwise = require('./utils/bitwise.js');
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
*/
|
||||
var DEFAULT_GROWING_POLICY = function(capacity) {
|
||||
return Math.max(1, Math.ceil(capacity * 1.5));
|
||||
};
|
||||
|
||||
/**
|
||||
* Helpers.
|
||||
*/
|
||||
function createByteArray(capacity) {
|
||||
return new Uint32Array(Math.ceil(capacity / 32));
|
||||
}
|
||||
|
||||
/**
|
||||
* BitVector.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function BitVector(initialLengthOrOptions) {
|
||||
var initialLength = initialLengthOrOptions || 0,
|
||||
policy = DEFAULT_GROWING_POLICY;
|
||||
|
||||
if (typeof initialLengthOrOptions === 'object') {
|
||||
initialLength = (
|
||||
initialLengthOrOptions.initialLength ||
|
||||
initialLengthOrOptions.initialCapacity ||
|
||||
0
|
||||
);
|
||||
policy = initialLengthOrOptions.policy || policy;
|
||||
}
|
||||
|
||||
this.size = 0;
|
||||
this.length = initialLength;
|
||||
this.capacity = Math.ceil(this.length / 32) * 32;
|
||||
this.policy = policy;
|
||||
this.array = createByteArray(this.capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to set the given bit's value.
|
||||
*
|
||||
* @param {number} index - Target bit index.
|
||||
* @param {number|boolean} value - Value to set.
|
||||
* @return {BitVector}
|
||||
*/
|
||||
BitVector.prototype.set = function(index, value) {
|
||||
|
||||
// Out of bounds?
|
||||
if (this.length < index)
|
||||
throw new Error('BitVector.set: index out of bounds.');
|
||||
|
||||
var byteIndex = index >> 5,
|
||||
pos = index & 0x0000001f,
|
||||
oldBytes = this.array[byteIndex],
|
||||
newBytes;
|
||||
|
||||
if (value === 0 || value === false)
|
||||
newBytes = this.array[byteIndex] &= ~(1 << pos);
|
||||
else
|
||||
newBytes = this.array[byteIndex] |= (1 << pos);
|
||||
|
||||
// Get unsigned representation.
|
||||
newBytes = newBytes >>> 0;
|
||||
|
||||
// Updating size
|
||||
if (newBytes > oldBytes)
|
||||
this.size++;
|
||||
else if (newBytes < oldBytes)
|
||||
this.size--;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to reset the given bit's value.
|
||||
*
|
||||
* @param {number} index - Target bit index.
|
||||
* @return {BitVector}
|
||||
*/
|
||||
BitVector.prototype.reset = function(index) {
|
||||
var byteIndex = index >> 5,
|
||||
pos = index & 0x0000001f,
|
||||
oldBytes = this.array[byteIndex],
|
||||
newBytes;
|
||||
|
||||
newBytes = this.array[byteIndex] &= ~(1 << pos);
|
||||
|
||||
// Updating size
|
||||
if (newBytes < oldBytes)
|
||||
this.size--;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to flip the value of the given bit.
|
||||
*
|
||||
* @param {number} index - Target bit index.
|
||||
* @return {BitVector}
|
||||
*/
|
||||
BitVector.prototype.flip = function(index) {
|
||||
var byteIndex = index >> 5,
|
||||
pos = index & 0x0000001f,
|
||||
oldBytes = this.array[byteIndex];
|
||||
|
||||
var newBytes = this.array[byteIndex] ^= (1 << pos);
|
||||
|
||||
// Get unsigned representation.
|
||||
newBytes = newBytes >>> 0;
|
||||
|
||||
// Updating size
|
||||
if (newBytes > oldBytes)
|
||||
this.size++;
|
||||
else if (newBytes < oldBytes)
|
||||
this.size--;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to apply the growing policy.
|
||||
*
|
||||
* @param {number} [override] - Override capacity.
|
||||
* @return {number}
|
||||
*/
|
||||
BitVector.prototype.applyPolicy = function(override) {
|
||||
var newCapacity = this.policy(override || this.capacity);
|
||||
|
||||
if (typeof newCapacity !== 'number' || newCapacity < 0)
|
||||
throw new Error('mnemonist/bit-vector.applyPolicy: policy returned an invalid value (expecting a positive integer).');
|
||||
|
||||
if (newCapacity <= this.capacity)
|
||||
throw new Error('mnemonist/bit-vector.applyPolicy: policy returned a less or equal capacity to allocate.');
|
||||
|
||||
// TODO: we should probably check that the returned number is an integer
|
||||
|
||||
// Ceil to nearest 32
|
||||
return Math.ceil(newCapacity / 32) * 32;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to reallocate the underlying array.
|
||||
*
|
||||
* @param {number} capacity - Target capacity.
|
||||
* @return {BitVector}
|
||||
*/
|
||||
BitVector.prototype.reallocate = function(capacity) {
|
||||
var virtualCapacity = capacity;
|
||||
|
||||
capacity = Math.ceil(capacity / 32) * 32;
|
||||
|
||||
if (virtualCapacity < this.length)
|
||||
this.length = virtualCapacity;
|
||||
|
||||
if (capacity === this.capacity)
|
||||
return this;
|
||||
|
||||
var oldArray = this.array;
|
||||
|
||||
var storageLength = capacity / 32;
|
||||
|
||||
if (storageLength === this.array.length)
|
||||
return this;
|
||||
|
||||
if (storageLength > this.array.length) {
|
||||
this.array = new Uint32Array(storageLength);
|
||||
this.array.set(oldArray, 0);
|
||||
}
|
||||
else {
|
||||
this.array = oldArray.slice(0, storageLength);
|
||||
}
|
||||
|
||||
this.capacity = capacity;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to grow the array.
|
||||
*
|
||||
* @param {number} [capacity] - Optional capacity to match.
|
||||
* @return {BitVector}
|
||||
*/
|
||||
BitVector.prototype.grow = function(capacity) {
|
||||
var newCapacity;
|
||||
|
||||
if (typeof capacity === 'number') {
|
||||
|
||||
if (this.capacity >= capacity)
|
||||
return this;
|
||||
|
||||
// We need to match the given capacity
|
||||
newCapacity = this.capacity;
|
||||
|
||||
while (newCapacity < capacity)
|
||||
newCapacity = this.applyPolicy(newCapacity);
|
||||
|
||||
this.reallocate(newCapacity);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// We need to run the policy once
|
||||
newCapacity = this.applyPolicy();
|
||||
this.reallocate(newCapacity);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to resize the array. Won't deallocate.
|
||||
*
|
||||
* @param {number} length - Target length.
|
||||
* @return {BitVector}
|
||||
*/
|
||||
BitVector.prototype.resize = function(length) {
|
||||
if (length === this.length)
|
||||
return this;
|
||||
|
||||
if (length < this.length) {
|
||||
this.length = length;
|
||||
return this;
|
||||
}
|
||||
|
||||
this.length = length;
|
||||
this.reallocate(length);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to push a value in the set.
|
||||
*
|
||||
* @param {number|boolean} value
|
||||
* @return {BitVector}
|
||||
*/
|
||||
BitVector.prototype.push = function(value) {
|
||||
if (this.capacity === this.length)
|
||||
this.grow();
|
||||
|
||||
if (value === 0 || value === false)
|
||||
return ++this.length;
|
||||
|
||||
this.size++;
|
||||
|
||||
var index = this.length++,
|
||||
byteIndex = index >> 5,
|
||||
pos = index & 0x0000001f;
|
||||
|
||||
this.array[byteIndex] |= (1 << pos);
|
||||
|
||||
return this.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to pop the last value of the set.
|
||||
*
|
||||
* @return {number} - The popped value.
|
||||
*/
|
||||
BitVector.prototype.pop = function() {
|
||||
if (this.length === 0)
|
||||
return;
|
||||
|
||||
var index = --this.length;
|
||||
|
||||
var byteIndex = index >> 5,
|
||||
pos = index & 0x0000001f;
|
||||
|
||||
return (this.array[byteIndex] >> pos) & 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the given bit's value.
|
||||
*
|
||||
* @param {number} index - Target bit index.
|
||||
* @return {number}
|
||||
*/
|
||||
BitVector.prototype.get = function(index) {
|
||||
if (this.length < index)
|
||||
return undefined;
|
||||
|
||||
var byteIndex = index >> 5,
|
||||
pos = index & 0x0000001f;
|
||||
|
||||
return (this.array[byteIndex] >> pos) & 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to test the given bit's value.
|
||||
*
|
||||
* @param {number} index - Target bit index.
|
||||
* @return {BitVector}
|
||||
*/
|
||||
BitVector.prototype.test = function(index) {
|
||||
if (this.length < index)
|
||||
return false;
|
||||
|
||||
return Boolean(this.get(index));
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to return the number of 1 from the beginning of the set up to
|
||||
* the ith index.
|
||||
*
|
||||
* @param {number} i - Ith index (cannot be > length).
|
||||
* @return {number}
|
||||
*/
|
||||
BitVector.prototype.rank = function(i) {
|
||||
if (this.size === 0)
|
||||
return 0;
|
||||
|
||||
var byteIndex = i >> 5,
|
||||
pos = i & 0x0000001f,
|
||||
r = 0;
|
||||
|
||||
// Accessing the bytes before the last one
|
||||
for (var j = 0; j < byteIndex; j++)
|
||||
r += bitwise.table8Popcount(this.array[j]);
|
||||
|
||||
// Handling masked last byte
|
||||
var maskedByte = this.array[byteIndex] & ((1 << pos) - 1);
|
||||
|
||||
r += bitwise.table8Popcount(maskedByte);
|
||||
|
||||
return r;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to return the position of the rth 1 in the set or -1 if the
|
||||
* set is empty.
|
||||
*
|
||||
* Note: usually select is implemented using binary search over rank but I
|
||||
* tend to think the following linear implementation is faster since here
|
||||
* rank is O(n) anyway.
|
||||
*
|
||||
* @param {number} r - Rth 1 to select (should be < length).
|
||||
* @return {number}
|
||||
*/
|
||||
BitVector.prototype.select = function(r) {
|
||||
if (this.size === 0)
|
||||
return -1;
|
||||
|
||||
// TODO: throw?
|
||||
if (r >= this.length)
|
||||
return -1;
|
||||
|
||||
var byte,
|
||||
b = 32,
|
||||
p = 0,
|
||||
c = 0;
|
||||
|
||||
for (var i = 0, l = this.array.length; i < l; i++) {
|
||||
byte = this.array[i];
|
||||
|
||||
// The byte is empty, let's continue
|
||||
if (byte === 0)
|
||||
continue;
|
||||
|
||||
// TODO: This branching might not be useful here
|
||||
if (i === l - 1)
|
||||
b = this.length % 32 || 32;
|
||||
|
||||
// TODO: popcount should speed things up here
|
||||
|
||||
for (var j = 0; j < b; j++, p++) {
|
||||
c += (byte >> j) & 1;
|
||||
|
||||
if (c === r)
|
||||
return p;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the bit set's values.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
BitVector.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
var length = this.length,
|
||||
byte,
|
||||
bit,
|
||||
b = 32;
|
||||
|
||||
for (var i = 0, l = this.array.length; i < l; i++) {
|
||||
byte = this.array[i];
|
||||
|
||||
if (i === l - 1)
|
||||
b = length % 32 || 32;
|
||||
|
||||
for (var j = 0; j < b; j++) {
|
||||
bit = (byte >> j) & 1;
|
||||
|
||||
callback.call(scope, bit, i * 32 + j);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a set's values.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
BitVector.prototype.values = function() {
|
||||
var length = this.length,
|
||||
inner = false,
|
||||
byte,
|
||||
bit,
|
||||
array = this.array,
|
||||
l = array.length,
|
||||
i = 0,
|
||||
j = -1,
|
||||
b = 32;
|
||||
|
||||
return new Iterator(function next() {
|
||||
if (!inner) {
|
||||
|
||||
if (i >= l)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
if (i === l - 1)
|
||||
b = length % 32 || 32;
|
||||
|
||||
byte = array[i++];
|
||||
inner = true;
|
||||
j = -1;
|
||||
}
|
||||
|
||||
j++;
|
||||
|
||||
if (j >= b) {
|
||||
inner = false;
|
||||
return next();
|
||||
}
|
||||
|
||||
bit = (byte >> j) & 1;
|
||||
|
||||
return {
|
||||
value: bit
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a set's entries.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
BitVector.prototype.entries = function() {
|
||||
var length = this.length,
|
||||
inner = false,
|
||||
byte,
|
||||
bit,
|
||||
array = this.array,
|
||||
index,
|
||||
l = array.length,
|
||||
i = 0,
|
||||
j = -1,
|
||||
b = 32;
|
||||
|
||||
return new Iterator(function next() {
|
||||
if (!inner) {
|
||||
|
||||
if (i >= l)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
if (i === l - 1)
|
||||
b = length % 32 || 32;
|
||||
|
||||
byte = array[i++];
|
||||
inner = true;
|
||||
j = -1;
|
||||
}
|
||||
|
||||
j++;
|
||||
index = (~-i) * 32 + j;
|
||||
|
||||
if (j >= b) {
|
||||
inner = false;
|
||||
return next();
|
||||
}
|
||||
|
||||
bit = (byte >> j) & 1;
|
||||
|
||||
return {
|
||||
value: [index, bit]
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.values method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
BitVector.prototype[Symbol.iterator] = BitVector.prototype.values;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
BitVector.prototype.inspect = function() {
|
||||
var proxy = new Uint8Array(this.length);
|
||||
|
||||
this.forEach(function(bit, i) {
|
||||
proxy[i] = bit;
|
||||
});
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: BitVector,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
BitVector.prototype[Symbol.for('nodejs.util.inspect.custom')] = BitVector.prototype.inspect;
|
||||
|
||||
BitVector.prototype.toJSON = function() {
|
||||
return Array.from(this.array.slice(0, (this.length >> 5) + 1));
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = BitVector;
|
||||
24
backend/node_modules/mnemonist/bk-tree.d.ts
generated
vendored
Normal file
24
backend/node_modules/mnemonist/bk-tree.d.ts
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Mnemonist BKTree Typings
|
||||
* =========================
|
||||
*/
|
||||
type DistanceFunction<T> = (a: T, b: T) => number;
|
||||
|
||||
export default class BKTree<T> {
|
||||
|
||||
// Members
|
||||
distance: DistanceFunction<T>;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(distance: DistanceFunction<T>);
|
||||
|
||||
// Methods
|
||||
add(item: T): this;
|
||||
search(n: number, query: T): Array<{item: T, distance: number}>;
|
||||
toJSON(): object;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(iterable: Iterable<I> | {[key: string]: I}, distance: DistanceFunction<I>): BKTree<I>;
|
||||
}
|
||||
180
backend/node_modules/mnemonist/bk-tree.js
generated
vendored
Normal file
180
backend/node_modules/mnemonist/bk-tree.js
generated
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
/* eslint no-constant-condition: 0 */
|
||||
/**
|
||||
* Mnemonist BK Tree
|
||||
* ==================
|
||||
*
|
||||
* Implementation of a Burkhard-Keller tree, allowing fast lookups of words
|
||||
* that lie within a specified distance of the query word.
|
||||
*
|
||||
* [Reference]:
|
||||
* https://en.wikipedia.org/wiki/BK-tree
|
||||
*
|
||||
* [Article]:
|
||||
* W. Burkhard and R. Keller. Some approaches to best-match file searching,
|
||||
* CACM, 1973
|
||||
*/
|
||||
var forEach = require('obliterator/foreach');
|
||||
|
||||
/**
|
||||
* BK Tree.
|
||||
*
|
||||
* @constructor
|
||||
* @param {function} distance - Distance function to use.
|
||||
*/
|
||||
function BKTree(distance) {
|
||||
|
||||
if (typeof distance !== 'function')
|
||||
throw new Error('mnemonist/BKTree.constructor: given `distance` should be a function.');
|
||||
|
||||
this.distance = distance;
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to add an item to the tree.
|
||||
*
|
||||
* @param {any} item - Item to add.
|
||||
* @return {BKTree}
|
||||
*/
|
||||
BKTree.prototype.add = function(item) {
|
||||
|
||||
// Initializing the tree with the first given word
|
||||
if (!this.root) {
|
||||
this.root = {
|
||||
item: item,
|
||||
children: {}
|
||||
};
|
||||
|
||||
this.size++;
|
||||
return this;
|
||||
}
|
||||
|
||||
var node = this.root,
|
||||
d;
|
||||
|
||||
while (true) {
|
||||
d = this.distance(item, node.item);
|
||||
|
||||
if (!node.children[d])
|
||||
break;
|
||||
|
||||
node = node.children[d];
|
||||
}
|
||||
|
||||
node.children[d] = {
|
||||
item: item,
|
||||
children: {}
|
||||
};
|
||||
|
||||
this.size++;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to query the tree.
|
||||
*
|
||||
* @param {number} n - Maximum distance between query & item.
|
||||
* @param {any} query - Query
|
||||
* @return {BKTree}
|
||||
*/
|
||||
BKTree.prototype.search = function(n, query) {
|
||||
if (!this.root)
|
||||
return [];
|
||||
|
||||
var found = [],
|
||||
stack = [this.root],
|
||||
node,
|
||||
child,
|
||||
d,
|
||||
i,
|
||||
l;
|
||||
|
||||
while (stack.length) {
|
||||
node = stack.pop();
|
||||
d = this.distance(query, node.item);
|
||||
|
||||
if (d <= n)
|
||||
found.push({item: node.item, distance: d});
|
||||
|
||||
for (i = d - n, l = d + n + 1; i < l; i++) {
|
||||
child = node.children[i];
|
||||
|
||||
if (child)
|
||||
stack.push(child);
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to clear the tree.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
BKTree.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
this.root = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
BKTree.prototype.toJSON = function() {
|
||||
return this.root;
|
||||
};
|
||||
|
||||
BKTree.prototype.inspect = function() {
|
||||
var array = [],
|
||||
stack = [this.root],
|
||||
node,
|
||||
d;
|
||||
|
||||
while (stack.length) {
|
||||
node = stack.pop();
|
||||
|
||||
if (!node)
|
||||
continue;
|
||||
|
||||
array.push(node.item);
|
||||
|
||||
for (d in node.children)
|
||||
stack.push(node.children[d]);
|
||||
}
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(array, 'constructor', {
|
||||
value: BKTree,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
BKTree.prototype[Symbol.for('nodejs.util.inspect.custom')] = BKTree.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a tree.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {function} distance - Distance function.
|
||||
* @return {Heap}
|
||||
*/
|
||||
BKTree.from = function(iterable, distance) {
|
||||
var tree = new BKTree(distance);
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
tree.add(value);
|
||||
});
|
||||
|
||||
return tree;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = BKTree;
|
||||
29
backend/node_modules/mnemonist/bloom-filter.d.ts
generated
vendored
Normal file
29
backend/node_modules/mnemonist/bloom-filter.d.ts
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Mnemonist BloomFilter Typings
|
||||
* ==============================
|
||||
*/
|
||||
type BloomFilterOptions = {
|
||||
capacity: number;
|
||||
errorRate?: number;
|
||||
}
|
||||
|
||||
export default class BloomFilter {
|
||||
|
||||
// Members
|
||||
capacity: number;
|
||||
errorRate: number;
|
||||
hashFunctions: number;
|
||||
|
||||
// Constructor
|
||||
constructor(capacity: number);
|
||||
constructor(options: BloomFilterOptions);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
add(string: string): this;
|
||||
test(string: string): boolean;
|
||||
toJSON(): Uint8Array;
|
||||
|
||||
// Statics
|
||||
from(iterable: Iterable<string>, options?: number | BloomFilterOptions): BloomFilter;
|
||||
}
|
||||
186
backend/node_modules/mnemonist/bloom-filter.js
generated
vendored
Normal file
186
backend/node_modules/mnemonist/bloom-filter.js
generated
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* Mnemonist Bloom Filter
|
||||
* =======================
|
||||
*
|
||||
* Bloom Filter implementation relying on MurmurHash3.
|
||||
*/
|
||||
var murmurhash3 = require('./utils/murmurhash3.js'),
|
||||
forEach = require('obliterator/foreach');
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
*/
|
||||
var LN2_SQUARED = Math.LN2 * Math.LN2;
|
||||
|
||||
/**
|
||||
* Defaults.
|
||||
*/
|
||||
var DEFAULTS = {
|
||||
errorRate: 0.005
|
||||
};
|
||||
|
||||
/**
|
||||
* Function used to convert a string into a Uint16 byte array.
|
||||
*
|
||||
* @param {string} string - Target string.
|
||||
* @return {Uint16Array}
|
||||
*/
|
||||
function stringToByteArray(string) {
|
||||
var array = new Uint16Array(string.length),
|
||||
i,
|
||||
l;
|
||||
|
||||
for (i = 0, l = string.length; i < l; i++)
|
||||
array[i] = string.charCodeAt(i);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to hash the given byte array.
|
||||
*
|
||||
* @param {number} length - Length of the filter's byte array.
|
||||
* @param {number} seed - Seed to use for the hash function.
|
||||
* @param {Uint16Array} - Byte array representing the string.
|
||||
* @return {number} - The hash.
|
||||
*
|
||||
* @note length * 8 should probably already be computed as well as seeds.
|
||||
*/
|
||||
function hashArray(length, seed, array) {
|
||||
var hash = murmurhash3((seed * 0xFBA4C795) & 0xFFFFFFFF, array);
|
||||
|
||||
return hash % (length * 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bloom Filter.
|
||||
*
|
||||
* @constructor
|
||||
* @param {number|object} capacityOrOptions - Capacity or options.
|
||||
*/
|
||||
function BloomFilter(capacityOrOptions) {
|
||||
var options = {};
|
||||
|
||||
if (!capacityOrOptions)
|
||||
throw new Error('mnemonist/BloomFilter.constructor: a BloomFilter must be created with a capacity.');
|
||||
|
||||
if (typeof capacityOrOptions === 'object')
|
||||
options = capacityOrOptions;
|
||||
else
|
||||
options.capacity = capacityOrOptions;
|
||||
|
||||
// Handling capacity
|
||||
if (typeof options.capacity !== 'number' || options.capacity <= 0)
|
||||
throw new Error('mnemonist/BloomFilter.constructor: `capacity` option should be a positive integer.');
|
||||
|
||||
this.capacity = options.capacity;
|
||||
|
||||
// Handling error rate
|
||||
this.errorRate = options.errorRate || DEFAULTS.errorRate;
|
||||
|
||||
if (typeof this.errorRate !== 'number' || options.errorRate <= 0)
|
||||
throw new Error('mnemonist/BloomFilter.constructor: `errorRate` option should be a positive float.');
|
||||
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the filter.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
BloomFilter.prototype.clear = function() {
|
||||
|
||||
// Optimizing number of bits & number of hash functions
|
||||
var bits = -1 / LN2_SQUARED * this.capacity * Math.log(this.errorRate),
|
||||
length = (bits / 8) | 0;
|
||||
|
||||
this.hashFunctions = (length * 8 / this.capacity * Math.LN2) | 0;
|
||||
|
||||
// Creating the data array
|
||||
this.data = new Uint8Array(length);
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add an string to the filter.
|
||||
*
|
||||
* @param {string} string - Item to add.
|
||||
* @return {BloomFilter}
|
||||
*
|
||||
* @note Should probably create a hash function working directly on a string.
|
||||
*/
|
||||
BloomFilter.prototype.add = function(string) {
|
||||
|
||||
// Converting the string to a byte array
|
||||
var array = stringToByteArray(string);
|
||||
|
||||
// Applying the n hash functions
|
||||
for (var i = 0, l = this.hashFunctions; i < l; i++) {
|
||||
var index = hashArray(this.data.length, i, array),
|
||||
position = (1 << (7 & index));
|
||||
|
||||
this.data[index >> 3] |= position;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to test the given string.
|
||||
*
|
||||
* @param {string} string - Item to test.
|
||||
* @return {boolean}
|
||||
*/
|
||||
BloomFilter.prototype.test = function(string) {
|
||||
|
||||
// Converting the string to a byte array
|
||||
var array = stringToByteArray(string);
|
||||
|
||||
// Applying the n hash functions
|
||||
for (var i = 0, l = this.hashFunctions; i < l; i++) {
|
||||
var index = hashArray(this.data.length, i, array);
|
||||
|
||||
if (!(this.data[index >> 3] & (1 << (7 & index))))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
BloomFilter.prototype.toJSON = function() {
|
||||
return this.data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a filter.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @return {BloomFilter}
|
||||
*/
|
||||
BloomFilter.from = function(iterable, options) {
|
||||
if (!options) {
|
||||
options = iterable.length || iterable.size;
|
||||
|
||||
if (typeof options !== 'number')
|
||||
throw new Error('BloomFilter.from: could not infer the filter\'s capacity. Try passing it as second argument.');
|
||||
}
|
||||
|
||||
var filter = new BloomFilter(options);
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
filter.add(value);
|
||||
});
|
||||
|
||||
return filter;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = BloomFilter;
|
||||
34
backend/node_modules/mnemonist/circular-buffer.d.ts
generated
vendored
Normal file
34
backend/node_modules/mnemonist/circular-buffer.d.ts
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Mnemonist CircularBuffer Typings
|
||||
* =================================
|
||||
*/
|
||||
import {IArrayLikeConstructor, TypedArray} from './utils/types';
|
||||
|
||||
export default class CircularBuffer<T> implements Iterable<T> {
|
||||
|
||||
// Members
|
||||
capacity: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(ArrayClass: IArrayLikeConstructor, capacity: number);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
push(item: T): number;
|
||||
unshift(item: T): number;
|
||||
pop(): T | undefined;
|
||||
shift(): T | undefined;
|
||||
peekFirst(): T | undefined;
|
||||
peekLast(): T | undefined;
|
||||
get(index: number): T | undefined;
|
||||
forEach(callback: (item: T, index: number, buffer: this) => void, scope?: any): void;
|
||||
toArray(): Array<T> | TypedArray;
|
||||
values(): IterableIterator<T>;
|
||||
entries(): IterableIterator<[number, T]>;
|
||||
[Symbol.iterator](): IterableIterator<T>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(iterable: Iterable<I> | {[key: string]: I}, ArrayClass: IArrayLikeConstructor, capacity?: number): CircularBuffer<I>;
|
||||
}
|
||||
131
backend/node_modules/mnemonist/circular-buffer.js
generated
vendored
Normal file
131
backend/node_modules/mnemonist/circular-buffer.js
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* Mnemonist CircularBuffer
|
||||
* =========================
|
||||
*
|
||||
* Circular buffer implementation fit to use as a finite deque.
|
||||
*/
|
||||
var iterables = require('./utils/iterables.js'),
|
||||
FixedDeque = require('./fixed-deque');
|
||||
|
||||
/**
|
||||
* CircularBuffer.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function CircularBuffer(ArrayClass, capacity) {
|
||||
|
||||
if (arguments.length < 2)
|
||||
throw new Error('mnemonist/circular-buffer: expecting an Array class and a capacity.');
|
||||
|
||||
if (typeof capacity !== 'number' || capacity <= 0)
|
||||
throw new Error('mnemonist/circular-buffer: `capacity` should be a positive number.');
|
||||
|
||||
this.ArrayClass = ArrayClass;
|
||||
this.capacity = capacity;
|
||||
this.items = new ArrayClass(this.capacity);
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pasting most of the prototype from FixedDeque.
|
||||
*/
|
||||
function paste(name) {
|
||||
CircularBuffer.prototype[name] = FixedDeque.prototype[name];
|
||||
}
|
||||
|
||||
Object.keys(FixedDeque.prototype).forEach(paste);
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
Object.getOwnPropertySymbols(FixedDeque.prototype).forEach(paste);
|
||||
|
||||
/**
|
||||
* Method used to append a value to the buffer.
|
||||
*
|
||||
* @param {any} item - Item to append.
|
||||
* @return {number} - Returns the new size of the buffer.
|
||||
*/
|
||||
CircularBuffer.prototype.push = function(item) {
|
||||
var index = (this.start + this.size) % this.capacity;
|
||||
|
||||
this.items[index] = item;
|
||||
|
||||
// Overwriting?
|
||||
if (this.size === this.capacity) {
|
||||
|
||||
// If start is at the end, we wrap around the buffer
|
||||
this.start = (index + 1) % this.capacity;
|
||||
|
||||
return this.size;
|
||||
}
|
||||
|
||||
return ++this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to prepend a value to the buffer.
|
||||
*
|
||||
* @param {any} item - Item to prepend.
|
||||
* @return {number} - Returns the new size of the buffer.
|
||||
*/
|
||||
CircularBuffer.prototype.unshift = function(item) {
|
||||
var index = this.start - 1;
|
||||
|
||||
if (this.start === 0)
|
||||
index = this.capacity - 1;
|
||||
|
||||
this.items[index] = item;
|
||||
|
||||
// Overwriting
|
||||
if (this.size === this.capacity) {
|
||||
|
||||
this.start = index;
|
||||
|
||||
return this.size;
|
||||
}
|
||||
|
||||
this.start = index;
|
||||
|
||||
return ++this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a circular buffer.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {function} ArrayClass - Array class to use.
|
||||
* @param {number} capacity - Desired capacity.
|
||||
* @return {FiniteStack}
|
||||
*/
|
||||
CircularBuffer.from = function(iterable, ArrayClass, capacity) {
|
||||
if (arguments.length < 3) {
|
||||
capacity = iterables.guessLength(iterable);
|
||||
|
||||
if (typeof capacity !== 'number')
|
||||
throw new Error('mnemonist/circular-buffer.from: could not guess iterable length. Please provide desired capacity as last argument.');
|
||||
}
|
||||
|
||||
var buffer = new CircularBuffer(ArrayClass, capacity);
|
||||
|
||||
if (iterables.isArrayLike(iterable)) {
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = iterable.length; i < l; i++)
|
||||
buffer.items[i] = iterable[i];
|
||||
|
||||
buffer.size = l;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
iterables.forEach(iterable, function(value) {
|
||||
buffer.push(value);
|
||||
});
|
||||
|
||||
return buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = CircularBuffer;
|
||||
515
backend/node_modules/mnemonist/critbit-tree-map.js
generated
vendored
Normal file
515
backend/node_modules/mnemonist/critbit-tree-map.js
generated
vendored
Normal file
@@ -0,0 +1,515 @@
|
||||
/* eslint no-constant-condition: 0 */
|
||||
/**
|
||||
* Mnemonist CritBitTreeMap
|
||||
* =========================
|
||||
*
|
||||
* JavaScript implementation of a crit-bit tree, also called PATRICIA tree.
|
||||
* This tree is a basically a bitwise radix tree and is supposedly much more
|
||||
* efficient than a standard Trie.
|
||||
*
|
||||
* [References]:
|
||||
* https://cr.yp.to/critbit.html
|
||||
* https://www.imperialviolet.org/binary/critbit.pdf
|
||||
*/
|
||||
var bitwise = require('./utils/bitwise.js');
|
||||
|
||||
/**
|
||||
* Helpers.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper returning the direction we need to take given a key and an
|
||||
* encoded critbit.
|
||||
*
|
||||
* @param {string} key - Target key.
|
||||
* @param {number} critbit - Packed address of byte + mask.
|
||||
* @return {number} - 0, left or 1, right.
|
||||
*/
|
||||
function getDirection(key, critbit) {
|
||||
var byteIndex = critbit >> 8;
|
||||
|
||||
if (byteIndex > key.length - 1)
|
||||
return 0;
|
||||
|
||||
var byte = key.charCodeAt(byteIndex),
|
||||
mask = critbit & 0xff;
|
||||
|
||||
return (1 + (byte | mask)) >> 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper returning the packed address of byte + mask or -1 if strings
|
||||
* are identical.
|
||||
*
|
||||
* @param {string} a - First key.
|
||||
* @param {string} b - Second key.
|
||||
* @return {number} - Packed address of byte + mask.
|
||||
*/
|
||||
function findCriticalBit(a, b) {
|
||||
var i = 0,
|
||||
tmp;
|
||||
|
||||
// Swapping so a is the shortest
|
||||
if (a.length > b.length) {
|
||||
tmp = b;
|
||||
b = a;
|
||||
a = tmp;
|
||||
}
|
||||
|
||||
var l = a.length,
|
||||
mask;
|
||||
|
||||
while (i < l) {
|
||||
if (a[i] !== b[i]) {
|
||||
mask = bitwise.criticalBit8Mask(
|
||||
a.charCodeAt(i),
|
||||
b.charCodeAt(i)
|
||||
);
|
||||
|
||||
return (i << 8) | mask;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// Strings are identical
|
||||
if (a.length === b.length)
|
||||
return -1;
|
||||
|
||||
// NOTE: x ^ 0 is the same as x
|
||||
mask = bitwise.criticalBit8Mask(b.charCodeAt(i));
|
||||
|
||||
return (i << 8) | mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing a crit-bit tree's internal node.
|
||||
*
|
||||
* @constructor
|
||||
* @param {number} critbit - Packed address of byte + mask.
|
||||
*/
|
||||
function InternalNode(critbit) {
|
||||
this.critbit = critbit;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing a crit-bit tree's external node.
|
||||
* Note that it is possible to replace those nodes by flat arrays.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} key - Node's key.
|
||||
* @param {any} value - Arbitrary value.
|
||||
*/
|
||||
function ExternalNode(key, value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* CritBitTreeMap.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function CritBitTreeMap() {
|
||||
|
||||
// Properties
|
||||
this.root = null;
|
||||
this.size = 0;
|
||||
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the CritBitTreeMap.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
CritBitTreeMap.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.root = null;
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set the value of the given key in the trie.
|
||||
*
|
||||
* @param {string} key - Key to set.
|
||||
* @param {any} value - Arbitrary value.
|
||||
* @return {CritBitTreeMap}
|
||||
*/
|
||||
CritBitTreeMap.prototype.set = function(key, value) {
|
||||
|
||||
// Tree is empty
|
||||
if (this.size === 0) {
|
||||
this.root = new ExternalNode(key, value);
|
||||
this.size++;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// Walk state
|
||||
var node = this.root,
|
||||
ancestors = [],
|
||||
path = [],
|
||||
ancestor,
|
||||
parent,
|
||||
child,
|
||||
critbit,
|
||||
internal,
|
||||
left,
|
||||
leftPath,
|
||||
best,
|
||||
dir,
|
||||
i,
|
||||
l;
|
||||
|
||||
// Walking the tree
|
||||
while (true) {
|
||||
|
||||
// Traversing an internal node
|
||||
if (node instanceof InternalNode) {
|
||||
dir = getDirection(key, node.critbit);
|
||||
|
||||
// Going left & creating key if not yet there
|
||||
if (dir === 0) {
|
||||
if (!node.left) {
|
||||
node.left = new ExternalNode(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
ancestors.push(node);
|
||||
path.push(true);
|
||||
|
||||
node = node.left;
|
||||
}
|
||||
|
||||
// Going right & creating key if not yet there
|
||||
else {
|
||||
if (!node.right) {
|
||||
node.right = new ExternalNode(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
ancestors.push(node);
|
||||
path.push(false);
|
||||
|
||||
node = node.right;
|
||||
}
|
||||
}
|
||||
|
||||
// Reaching an external node
|
||||
else {
|
||||
|
||||
// 1. Creating a new external node
|
||||
critbit = findCriticalBit(key, node.key);
|
||||
|
||||
// Key is identical, we just replace the value
|
||||
if (critbit === -1) {
|
||||
node.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
this.size++;
|
||||
|
||||
internal = new InternalNode(critbit);
|
||||
|
||||
left = getDirection(key, critbit) === 0;
|
||||
|
||||
// TODO: maybe setting opposite pointer is not necessary
|
||||
if (left) {
|
||||
internal.left = new ExternalNode(key, value);
|
||||
internal.right = node;
|
||||
}
|
||||
else {
|
||||
internal.left = node;
|
||||
internal.right = new ExternalNode(key, value);
|
||||
}
|
||||
|
||||
// 2. Bubbling up
|
||||
best = -1;
|
||||
l = ancestors.length;
|
||||
|
||||
for (i = l - 1; i >= 0; i--) {
|
||||
ancestor = ancestors[i];
|
||||
|
||||
if (ancestor.critbit > critbit)
|
||||
continue;
|
||||
|
||||
best = i;
|
||||
break;
|
||||
}
|
||||
|
||||
// Do we need to attach to the root?
|
||||
if (best < 0) {
|
||||
this.root = internal;
|
||||
|
||||
// Need to rewire parent as child?
|
||||
if (l > 0) {
|
||||
parent = ancestors[0];
|
||||
|
||||
if (left)
|
||||
internal.right = parent;
|
||||
else
|
||||
internal.left = parent;
|
||||
}
|
||||
}
|
||||
|
||||
// Simple case without rotation
|
||||
else if (best === l - 1) {
|
||||
parent = ancestors[best];
|
||||
leftPath = path[best];
|
||||
|
||||
if (leftPath)
|
||||
parent.left = internal;
|
||||
else
|
||||
parent.right = internal;
|
||||
}
|
||||
|
||||
// Full rotation
|
||||
else {
|
||||
parent = ancestors[best];
|
||||
leftPath = path[best];
|
||||
child = ancestors[best + 1];
|
||||
|
||||
if (leftPath)
|
||||
parent.left = internal;
|
||||
else
|
||||
parent.right = internal;
|
||||
|
||||
if (left)
|
||||
internal.right = child;
|
||||
else
|
||||
internal.left = child;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the value attached to the given key in the tree or
|
||||
* undefined if not found.
|
||||
*
|
||||
* @param {string} key - Key to get.
|
||||
* @return {any}
|
||||
*/
|
||||
CritBitTreeMap.prototype.get = function(key) {
|
||||
|
||||
// Walk state
|
||||
var node = this.root,
|
||||
dir;
|
||||
|
||||
// Walking the tree
|
||||
while (true) {
|
||||
|
||||
// Dead end
|
||||
if (node === null)
|
||||
return;
|
||||
|
||||
// Traversing an internal node
|
||||
if (node instanceof InternalNode) {
|
||||
dir = getDirection(key, node.critbit);
|
||||
|
||||
node = dir ? node.right : node.left;
|
||||
}
|
||||
|
||||
// Reaching an external node
|
||||
else {
|
||||
if (node.key !== key)
|
||||
return;
|
||||
|
||||
return node.value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to return whether the given key exists in the tree.
|
||||
*
|
||||
* @param {string} key - Key to test.
|
||||
* @return {boolean}
|
||||
*/
|
||||
CritBitTreeMap.prototype.has = function(key) {
|
||||
|
||||
// Walk state
|
||||
var node = this.root,
|
||||
dir;
|
||||
|
||||
// Walking the tree
|
||||
while (true) {
|
||||
|
||||
// Dead end
|
||||
if (node === null)
|
||||
return false;
|
||||
|
||||
// Traversing an internal node
|
||||
if (node instanceof InternalNode) {
|
||||
dir = getDirection(key, node.critbit);
|
||||
|
||||
node = dir ? node.right : node.left;
|
||||
}
|
||||
|
||||
// Reaching an external node
|
||||
else {
|
||||
return node.key === key;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to delete the given key from the tree and return whether the
|
||||
* key did exist or not.
|
||||
*
|
||||
* @param {string} key - Key to delete.
|
||||
* @return {boolean}
|
||||
*/
|
||||
CritBitTreeMap.prototype.delete = function(key) {
|
||||
|
||||
// Walk state
|
||||
var node = this.root,
|
||||
dir;
|
||||
|
||||
var parent = null,
|
||||
grandParent = null,
|
||||
wentLeftForParent = false,
|
||||
wentLeftForGrandparent = false;
|
||||
|
||||
// Walking the tree
|
||||
while (true) {
|
||||
|
||||
// Dead end
|
||||
if (node === null)
|
||||
return false;
|
||||
|
||||
// Traversing an internal node
|
||||
if (node instanceof InternalNode) {
|
||||
dir = getDirection(key, node.critbit);
|
||||
|
||||
if (dir === 0) {
|
||||
grandParent = parent;
|
||||
wentLeftForGrandparent = wentLeftForParent;
|
||||
parent = node;
|
||||
wentLeftForParent = true;
|
||||
|
||||
node = node.left;
|
||||
}
|
||||
else {
|
||||
grandParent = parent;
|
||||
wentLeftForGrandparent = wentLeftForParent;
|
||||
parent = node;
|
||||
wentLeftForParent = false;
|
||||
|
||||
node = node.right;
|
||||
}
|
||||
}
|
||||
|
||||
// Reaching an external node
|
||||
else {
|
||||
if (key !== node.key)
|
||||
return false;
|
||||
|
||||
this.size--;
|
||||
|
||||
// Rewiring
|
||||
if (parent === null) {
|
||||
this.root = null;
|
||||
}
|
||||
|
||||
else if (grandParent === null) {
|
||||
if (wentLeftForParent)
|
||||
this.root = parent.right;
|
||||
else
|
||||
this.root = parent.left;
|
||||
}
|
||||
|
||||
else {
|
||||
if (wentLeftForGrandparent) {
|
||||
if (wentLeftForParent) {
|
||||
grandParent.left = parent.right;
|
||||
}
|
||||
else {
|
||||
grandParent.left = parent.left;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (wentLeftForParent) {
|
||||
grandParent.right = parent.right;
|
||||
}
|
||||
else {
|
||||
grandParent.right = parent.left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the tree in key order.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
CritBitTreeMap.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
// Inorder traversal of the tree
|
||||
var current = this.root,
|
||||
stack = [];
|
||||
|
||||
while (true) {
|
||||
|
||||
if (current !== null) {
|
||||
stack.push(current);
|
||||
|
||||
current = current instanceof InternalNode ? current.left : null;
|
||||
}
|
||||
|
||||
else {
|
||||
if (stack.length > 0) {
|
||||
current = stack.pop();
|
||||
|
||||
if (current instanceof ExternalNode)
|
||||
callback.call(scope, current.value, current.key);
|
||||
|
||||
current = current instanceof InternalNode ? current.right : null;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
CritBitTreeMap.prototype.inspect = function() {
|
||||
return this;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
CritBitTreeMap.prototype[Symbol.for('nodejs.util.inspect.custom')] = CritBitTreeMap.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a CritBitTreeMap.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @return {CritBitTreeMap}
|
||||
*/
|
||||
// CritBitTreeMap.from = function(iterable) {
|
||||
|
||||
// };
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = CritBitTreeMap;
|
||||
29
backend/node_modules/mnemonist/default-map.d.ts
generated
vendored
Normal file
29
backend/node_modules/mnemonist/default-map.d.ts
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Mnemonist DefaultMap Typings
|
||||
* =============================
|
||||
*/
|
||||
export default class DefaultMap<K, V> implements Iterable<[K, V]> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(factory: (key: K, index: number) => V);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
set(key: K, value: V): this;
|
||||
delete(key: K): boolean;
|
||||
has(key: K): boolean;
|
||||
get(key: K): V;
|
||||
peek(key: K): V | undefined;
|
||||
forEach(callback: (value: V, key: K, map: this) => void, scope?: any): void;
|
||||
keys(): IterableIterator<K>;
|
||||
values(): IterableIterator<V>;
|
||||
entries(): IterableIterator<[K, V]>;
|
||||
[Symbol.iterator](): IterableIterator<[K, V]>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static autoIncrement(): number;
|
||||
}
|
||||
162
backend/node_modules/mnemonist/default-map.js
generated
vendored
Normal file
162
backend/node_modules/mnemonist/default-map.js
generated
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* Mnemonist DefaultMap
|
||||
* =====================
|
||||
*
|
||||
* JavaScript implementation of a default map that will return a constructed
|
||||
* value any time one tries to access an inexisting key. It's quite similar
|
||||
* to python's defaultdict.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DefaultMap.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function DefaultMap(factory) {
|
||||
if (typeof factory !== 'function')
|
||||
throw new Error('mnemonist/DefaultMap.constructor: expecting a function.');
|
||||
|
||||
this.items = new Map();
|
||||
this.factory = factory;
|
||||
this.size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
DefaultMap.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.items.clear();
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the value set for given key. If the key does not exist,
|
||||
* the value will be created using the provided factory.
|
||||
*
|
||||
* @param {any} key - Target key.
|
||||
* @return {any}
|
||||
*/
|
||||
DefaultMap.prototype.get = function(key) {
|
||||
var value = this.items.get(key);
|
||||
|
||||
if (typeof value === 'undefined') {
|
||||
value = this.factory(key, this.size);
|
||||
this.items.set(key, value);
|
||||
this.size++;
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the value set for given key. If the key does not exist,
|
||||
* a value won't be created.
|
||||
*
|
||||
* @param {any} key - Target key.
|
||||
* @return {any}
|
||||
*/
|
||||
DefaultMap.prototype.peek = function(key) {
|
||||
return this.items.get(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set a value for given key.
|
||||
*
|
||||
* @param {any} key - Target key.
|
||||
* @param {any} value - Value.
|
||||
* @return {DefaultMap}
|
||||
*/
|
||||
DefaultMap.prototype.set = function(key, value) {
|
||||
this.items.set(key, value);
|
||||
this.size = this.items.size;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to test the existence of a key in the map.
|
||||
*
|
||||
* @param {any} key - Target key.
|
||||
* @return {boolean}
|
||||
*/
|
||||
DefaultMap.prototype.has = function(key) {
|
||||
return this.items.has(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to delete target key.
|
||||
*
|
||||
* @param {any} key - Target key.
|
||||
* @return {boolean}
|
||||
*/
|
||||
DefaultMap.prototype.delete = function(key) {
|
||||
var deleted = this.items.delete(key);
|
||||
|
||||
this.size = this.items.size;
|
||||
|
||||
return deleted;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over each of the key/value pairs.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
DefaultMap.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
this.items.forEach(callback, scope);
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterators.
|
||||
*/
|
||||
DefaultMap.prototype.entries = function() {
|
||||
return this.items.entries();
|
||||
};
|
||||
|
||||
DefaultMap.prototype.keys = function() {
|
||||
return this.items.keys();
|
||||
};
|
||||
|
||||
DefaultMap.prototype.values = function() {
|
||||
return this.items.values();
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.entries method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
DefaultMap.prototype[Symbol.iterator] = DefaultMap.prototype.entries;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
DefaultMap.prototype.inspect = function() {
|
||||
return this.items;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
DefaultMap.prototype[Symbol.for('nodejs.util.inspect.custom')] = DefaultMap.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Typical factories.
|
||||
*/
|
||||
DefaultMap.autoIncrement = function() {
|
||||
var i = 0;
|
||||
|
||||
return function() {
|
||||
return i++;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = DefaultMap;
|
||||
18
backend/node_modules/mnemonist/default-weak-map.d.ts
generated
vendored
Normal file
18
backend/node_modules/mnemonist/default-weak-map.d.ts
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Mnemonist DefaultWeakMap Typings
|
||||
* ================================
|
||||
*/
|
||||
export default class DefaultWeakMap<K extends object, V> {
|
||||
|
||||
// Constructor
|
||||
constructor(factory: (key: K) => V);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
set(key: K, value: V): this;
|
||||
delete(key: K): boolean;
|
||||
has(key: K): boolean;
|
||||
get(key: K): V;
|
||||
peek(key: K): V | undefined;
|
||||
inspect(): any;
|
||||
}
|
||||
108
backend/node_modules/mnemonist/default-weak-map.js
generated
vendored
Normal file
108
backend/node_modules/mnemonist/default-weak-map.js
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Mnemonist DefaultWeakMap
|
||||
* =========================
|
||||
*
|
||||
* JavaScript implementation of a default weak map that will return a constructed
|
||||
* value any time one tries to access an non-existing key. It is similar to
|
||||
* DefaultMap but uses ES6 WeakMap that only holds weak reference to keys.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DefaultWeakMap.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function DefaultWeakMap(factory) {
|
||||
if (typeof factory !== 'function')
|
||||
throw new Error('mnemonist/DefaultWeakMap.constructor: expecting a function.');
|
||||
|
||||
this.items = new WeakMap();
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
DefaultWeakMap.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.items = new WeakMap();
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the value set for given key. If the key does not exist,
|
||||
* the value will be created using the provided factory.
|
||||
*
|
||||
* @param {any} key - Target key.
|
||||
* @return {any}
|
||||
*/
|
||||
DefaultWeakMap.prototype.get = function(key) {
|
||||
var value = this.items.get(key);
|
||||
|
||||
if (typeof value === 'undefined') {
|
||||
value = this.factory(key);
|
||||
this.items.set(key, value);
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the value set for given key. If the key does not exist,
|
||||
* a value won't be created.
|
||||
*
|
||||
* @param {any} key - Target key.
|
||||
* @return {any}
|
||||
*/
|
||||
DefaultWeakMap.prototype.peek = function(key) {
|
||||
return this.items.get(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set a value for given key.
|
||||
*
|
||||
* @param {any} key - Target key.
|
||||
* @param {any} value - Value.
|
||||
* @return {DefaultMap}
|
||||
*/
|
||||
DefaultWeakMap.prototype.set = function(key, value) {
|
||||
this.items.set(key, value);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to test the existence of a key in the map.
|
||||
*
|
||||
* @param {any} key - Target key.
|
||||
* @return {boolean}
|
||||
*/
|
||||
DefaultWeakMap.prototype.has = function(key) {
|
||||
return this.items.has(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to delete target key.
|
||||
*
|
||||
* @param {any} key - Target key.
|
||||
* @return {boolean}
|
||||
*/
|
||||
DefaultWeakMap.prototype.delete = function(key) {
|
||||
return this.items.delete(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
DefaultWeakMap.prototype.inspect = function() {
|
||||
return this.items;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
DefaultWeakMap.prototype[Symbol.for('nodejs.util.inspect.custom')] = DefaultWeakMap.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = DefaultWeakMap;
|
||||
71
backend/node_modules/mnemonist/fibonacci-heap.d.ts
generated
vendored
Normal file
71
backend/node_modules/mnemonist/fibonacci-heap.d.ts
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Mnemonist FibonacciHeap Typings
|
||||
* ================================
|
||||
*/
|
||||
type FibonacciHeapComparator<T> = (a: T, b: T) => number;
|
||||
|
||||
export default class FibonacciHeap<T> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(comparator?: FibonacciHeapComparator<T>);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
push(item: T): number;
|
||||
peek(): T | undefined;
|
||||
pop(): T | undefined;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(
|
||||
iterable: Iterable<I> | {[key: string]: I},
|
||||
comparator?: FibonacciHeapComparator<I>
|
||||
): FibonacciHeap<I>;
|
||||
}
|
||||
|
||||
export class MinFibonacciHeap<T> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(comparator?: FibonacciHeapComparator<T>);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
push(item: T): number;
|
||||
peek(): T | undefined;
|
||||
pop(): T | undefined;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(
|
||||
iterable: Iterable<I> | {[key: string]: I},
|
||||
comparator?: FibonacciHeapComparator<I>
|
||||
): FibonacciHeap<I>;
|
||||
}
|
||||
|
||||
export class MaxFibonacciHeap<T> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(comparator?: FibonacciHeapComparator<T>);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
push(item: T): number;
|
||||
peek(): T | undefined;
|
||||
pop(): T | undefined;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(
|
||||
iterable: Iterable<I> | {[key: string]: I},
|
||||
comparator?: FibonacciHeapComparator<I>
|
||||
): FibonacciHeap<I>;
|
||||
}
|
||||
320
backend/node_modules/mnemonist/fibonacci-heap.js
generated
vendored
Normal file
320
backend/node_modules/mnemonist/fibonacci-heap.js
generated
vendored
Normal file
@@ -0,0 +1,320 @@
|
||||
/* eslint no-constant-condition: 0 */
|
||||
/**
|
||||
* Mnemonist Fibonacci Heap
|
||||
* =========================
|
||||
*
|
||||
* Fibonacci heap implementation.
|
||||
*/
|
||||
var comparators = require('./utils/comparators.js'),
|
||||
forEach = require('obliterator/foreach');
|
||||
|
||||
var DEFAULT_COMPARATOR = comparators.DEFAULT_COMPARATOR,
|
||||
reverseComparator = comparators.reverseComparator;
|
||||
|
||||
/**
|
||||
* Fibonacci Heap.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function FibonacciHeap(comparator) {
|
||||
this.clear();
|
||||
this.comparator = comparator || DEFAULT_COMPARATOR;
|
||||
|
||||
if (typeof this.comparator !== 'function')
|
||||
throw new Error('mnemonist/FibonacciHeap.constructor: given comparator should be a function.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the heap.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
FibonacciHeap.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.root = null;
|
||||
this.min = null;
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function used to create a node.
|
||||
*
|
||||
* @param {any} item - Target item.
|
||||
* @return {object}
|
||||
*/
|
||||
function createNode(item) {
|
||||
return {
|
||||
item: item,
|
||||
degree: 0
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to merge the given node with the root list.
|
||||
*
|
||||
* @param {FibonacciHeap} heap - Target heap.
|
||||
* @param {Node} node - Target node.
|
||||
*/
|
||||
function mergeWithRoot(heap, node) {
|
||||
if (!heap.root) {
|
||||
heap.root = node;
|
||||
}
|
||||
else {
|
||||
node.right = heap.root.right;
|
||||
node.left = heap.root;
|
||||
heap.root.right.left = node;
|
||||
heap.root.right = node;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to push an item into the heap.
|
||||
*
|
||||
* @param {any} item - Item to push.
|
||||
* @return {number}
|
||||
*/
|
||||
FibonacciHeap.prototype.push = function(item) {
|
||||
var node = createNode(item);
|
||||
node.left = node;
|
||||
node.right = node;
|
||||
mergeWithRoot(this, node);
|
||||
|
||||
if (!this.min || this.comparator(node.item, this.min.item) <= 0)
|
||||
this.min = node;
|
||||
|
||||
return ++this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the "first" item of the heap.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
FibonacciHeap.prototype.peek = function() {
|
||||
return this.min ? this.min.item : undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function used to consume the given linked list.
|
||||
*
|
||||
* @param {Node} head - Head node.
|
||||
* @param {array}
|
||||
*/
|
||||
function consumeLinkedList(head) {
|
||||
var nodes = [],
|
||||
node = head,
|
||||
flag = false;
|
||||
|
||||
while (true) {
|
||||
if (node === head && flag)
|
||||
break;
|
||||
else if (node === head)
|
||||
flag = true;
|
||||
|
||||
nodes.push(node);
|
||||
node = node.right;
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to remove the target node from the root list.
|
||||
*
|
||||
* @param {FibonacciHeap} heap - Target heap.
|
||||
* @param {Node} node - Target node.
|
||||
*/
|
||||
function removeFromRoot(heap, node) {
|
||||
if (heap.root === node)
|
||||
heap.root = node.right;
|
||||
node.left.right = node.right;
|
||||
node.right.left = node.left;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to merge the given node with the child list of a root node.
|
||||
*
|
||||
* @param {Node} parent - Parent node.
|
||||
* @param {Node} node - Target node.
|
||||
*/
|
||||
function mergeWithChild(parent, node) {
|
||||
if (!parent.child) {
|
||||
parent.child = node;
|
||||
}
|
||||
else {
|
||||
node.right = parent.child.right;
|
||||
node.left = parent.child;
|
||||
parent.child.right.left = node;
|
||||
parent.child.right = node;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to link one node to another in the root list.
|
||||
*
|
||||
* @param {FibonacciHeap} heap - Target heap.
|
||||
* @param {Node} y - Y node.
|
||||
* @param {Node} x - X node.
|
||||
*/
|
||||
function link(heap, y, x) {
|
||||
removeFromRoot(heap, y);
|
||||
y.left = y;
|
||||
y.right = y;
|
||||
mergeWithChild(x, y);
|
||||
x.degree++;
|
||||
y.parent = x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to consolidate the heap.
|
||||
*
|
||||
* @param {FibonacciHeap} heap - Target heap.
|
||||
*/
|
||||
function consolidate(heap) {
|
||||
var A = new Array(heap.size),
|
||||
nodes = consumeLinkedList(heap.root),
|
||||
i, l, x, y, d, t;
|
||||
|
||||
for (i = 0, l = nodes.length; i < l; i++) {
|
||||
x = nodes[i];
|
||||
d = x.degree;
|
||||
|
||||
while (A[d]) {
|
||||
y = A[d];
|
||||
|
||||
if (heap.comparator(x.item, y.item) > 0) {
|
||||
t = x;
|
||||
x = y;
|
||||
y = t;
|
||||
}
|
||||
|
||||
link(heap, y, x);
|
||||
A[d] = null;
|
||||
d++;
|
||||
}
|
||||
|
||||
A[d] = x;
|
||||
}
|
||||
|
||||
for (i = 0; i < heap.size; i++) {
|
||||
if (A[i] && heap.comparator(A[i].item, heap.min.item) <= 0)
|
||||
heap.min = A[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to retrieve & remove the "first" item of the heap.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
FibonacciHeap.prototype.pop = function() {
|
||||
if (!this.size)
|
||||
return undefined;
|
||||
|
||||
var z = this.min;
|
||||
|
||||
if (z.child) {
|
||||
var nodes = consumeLinkedList(z.child),
|
||||
node,
|
||||
i,
|
||||
l;
|
||||
|
||||
for (i = 0, l = nodes.length; i < l; i++) {
|
||||
node = nodes[i];
|
||||
|
||||
mergeWithRoot(this, node);
|
||||
delete node.parent;
|
||||
}
|
||||
}
|
||||
|
||||
removeFromRoot(this, z);
|
||||
|
||||
if (z === z.right) {
|
||||
this.min = null;
|
||||
this.root = null;
|
||||
}
|
||||
else {
|
||||
this.min = z.right;
|
||||
consolidate(this);
|
||||
}
|
||||
|
||||
this.size--;
|
||||
|
||||
return z.item;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
FibonacciHeap.prototype.inspect = function() {
|
||||
var proxy = {
|
||||
size: this.size
|
||||
};
|
||||
|
||||
if (this.min && 'item' in this.min)
|
||||
proxy.top = this.min.item;
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: FibonacciHeap,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
FibonacciHeap.prototype[Symbol.for('nodejs.util.inspect.custom')] = FibonacciHeap.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Fibonacci Maximum Heap.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function MaxFibonacciHeap(comparator) {
|
||||
this.clear();
|
||||
this.comparator = comparator || DEFAULT_COMPARATOR;
|
||||
|
||||
if (typeof this.comparator !== 'function')
|
||||
throw new Error('mnemonist/FibonacciHeap.constructor: given comparator should be a function.');
|
||||
|
||||
this.comparator = reverseComparator(this.comparator);
|
||||
}
|
||||
|
||||
MaxFibonacciHeap.prototype = FibonacciHeap.prototype;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a heap.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {function} comparator - Custom comparator function.
|
||||
* @return {FibonacciHeap}
|
||||
*/
|
||||
FibonacciHeap.from = function(iterable, comparator) {
|
||||
var heap = new FibonacciHeap(comparator);
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
heap.push(value);
|
||||
});
|
||||
|
||||
return heap;
|
||||
};
|
||||
|
||||
MaxFibonacciHeap.from = function(iterable, comparator) {
|
||||
var heap = new MaxFibonacciHeap(comparator);
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
heap.push(value);
|
||||
});
|
||||
|
||||
return heap;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
FibonacciHeap.MinFibonacciHeap = FibonacciHeap;
|
||||
FibonacciHeap.MaxFibonacciHeap = MaxFibonacciHeap;
|
||||
module.exports = FibonacciHeap;
|
||||
427
backend/node_modules/mnemonist/fixed-critbit-tree-map.js
generated
vendored
Normal file
427
backend/node_modules/mnemonist/fixed-critbit-tree-map.js
generated
vendored
Normal file
@@ -0,0 +1,427 @@
|
||||
/* eslint no-constant-condition: 0 */
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
* Mnemonist FixedFixedCritBitTreeMap
|
||||
* ===================================
|
||||
*
|
||||
* TODO...
|
||||
*
|
||||
* [References]:
|
||||
* https://cr.yp.to/critbit.html
|
||||
* https://www.imperialviolet.org/binary/critbit.pdf
|
||||
*/
|
||||
var bitwise = require('./utils/bitwise.js'),
|
||||
typed = require('./utils/typed-arrays.js');
|
||||
|
||||
/**
|
||||
* Helpers.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper returning the direction we need to take given a key and an
|
||||
* encoded critbit.
|
||||
*
|
||||
* @param {string} key - Target key.
|
||||
* @param {number} critbit - Packed address of byte + mask.
|
||||
* @return {number} - 0, left or 1, right.
|
||||
*/
|
||||
function getDirection(key, critbit) {
|
||||
var byteIndex = critbit >> 8;
|
||||
|
||||
if (byteIndex > key.length - 1)
|
||||
return 0;
|
||||
|
||||
var byte = key.charCodeAt(byteIndex),
|
||||
mask = critbit & 0xff;
|
||||
|
||||
return byte & mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper returning the packed address of byte + mask or -1 if strings
|
||||
* are identical.
|
||||
*
|
||||
* @param {string} a - First key.
|
||||
* @param {string} b - Second key.
|
||||
* @return {number} - Packed address of byte + mask.
|
||||
*/
|
||||
function findCriticalBit(a, b) {
|
||||
var i = 0,
|
||||
tmp;
|
||||
|
||||
// Swapping so a is the shortest
|
||||
if (a.length > b.length) {
|
||||
tmp = b;
|
||||
b = a;
|
||||
a = tmp;
|
||||
}
|
||||
|
||||
var l = a.length,
|
||||
mask;
|
||||
|
||||
while (i < l) {
|
||||
if (a[i] !== b[i]) {
|
||||
mask = bitwise.msb8(
|
||||
a.charCodeAt(i) ^ b.charCodeAt(i)
|
||||
);
|
||||
|
||||
return (i << 8) | mask;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// Strings are identical
|
||||
if (a.length === b.length)
|
||||
return -1;
|
||||
|
||||
// NOTE: x ^ 0 is the same as x
|
||||
mask = bitwise.msb8(b.charCodeAt(i));
|
||||
|
||||
return (i << 8) | mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* FixedCritBitTreeMap.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function FixedCritBitTreeMap(capacity) {
|
||||
|
||||
if (typeof capacity !== 'number' || capacity <= 0)
|
||||
throw new Error('mnemonist/fixed-critbit-tree-map: `capacity` should be a positive number.');
|
||||
|
||||
// Properties
|
||||
this.capacity = capacity;
|
||||
this.offset = 0;
|
||||
this.root = 0;
|
||||
this.size = 0;
|
||||
|
||||
var PointerArray = typed.getSignedPointerArray(capacity + 1);
|
||||
|
||||
this.keys = new Array(capacity);
|
||||
this.values = new Array(capacity);
|
||||
this.lefts = new PointerArray(capacity - 1);
|
||||
this.rights = new PointerArray(capacity - 1);
|
||||
this.critbits = new Uint32Array(capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the FixedCritBitTreeMap.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
FixedCritBitTreeMap.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
// TODO...
|
||||
this.root = null;
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set the value of the given key in the trie.
|
||||
*
|
||||
* @param {string} key - Key to set.
|
||||
* @param {any} value - Arbitrary value.
|
||||
* @return {FixedCritBitTreeMap}
|
||||
*/
|
||||
FixedCritBitTreeMap.prototype.set = function(key, value) {
|
||||
var pointer;
|
||||
|
||||
// TODO: yell if capacity is already full!
|
||||
|
||||
// Tree is empty
|
||||
if (this.size === 0) {
|
||||
this.keys[0] = key;
|
||||
this.values[0] = value;
|
||||
|
||||
this.size++;
|
||||
|
||||
this.root = -1;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// Walk state
|
||||
var pointer = this.root,
|
||||
newPointer,
|
||||
leftOrRight,
|
||||
opposite,
|
||||
ancestors = [],
|
||||
path = [],
|
||||
ancestor,
|
||||
parent,
|
||||
child,
|
||||
critbit,
|
||||
internal,
|
||||
best,
|
||||
dir,
|
||||
i,
|
||||
l;
|
||||
|
||||
// Walking the tree
|
||||
while (true) {
|
||||
|
||||
// Traversing an internal node
|
||||
if (pointer > 0) {
|
||||
pointer -= 1;
|
||||
|
||||
// Choosing the correct direction
|
||||
dir = getDirection(key, this.critbits[pointer]);
|
||||
|
||||
leftOrRight = dir === 0 ? this.lefts : this.rights;
|
||||
newPointer = leftOrRight[pointer];
|
||||
|
||||
if (newPointer === 0) {
|
||||
|
||||
// Creating a fitting external node
|
||||
pointer = this.size++;
|
||||
leftOrRight[newPointer] = -(pointer + 1);
|
||||
this.keys[pointer] = key;
|
||||
this.values[pointer] = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
ancestors.push(pointer);
|
||||
path.push(dir);
|
||||
pointer = newPointer;
|
||||
}
|
||||
|
||||
// Reaching an external node
|
||||
else {
|
||||
pointer = -pointer;
|
||||
pointer -= 1;
|
||||
|
||||
// 1. Creating a new external node
|
||||
critbit = findCriticalBit(key, this.keys[pointer]);
|
||||
|
||||
// Key is identical, we just replace the value
|
||||
if (critbit === -1) {
|
||||
this.values[pointer] = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
internal = this.offset++;
|
||||
newPointer = this.size++;
|
||||
|
||||
this.keys[newPointer] = key;
|
||||
this.values[newPointer] = value;
|
||||
|
||||
this.critbits[internal] = critbit;
|
||||
|
||||
dir = getDirection(key, critbit);
|
||||
leftOrRight = dir === 0 ? this.lefts : this.rights;
|
||||
opposite = dir === 0 ? this.rights : this.lefts;
|
||||
|
||||
leftOrRight[internal] = -(newPointer + 1);
|
||||
opposite[internal] = -(pointer + 1);
|
||||
|
||||
// 2. Bubbling up
|
||||
best = -1;
|
||||
l = ancestors.length;
|
||||
|
||||
for (i = l - 1; i >= 0; i--) {
|
||||
ancestor = ancestors[i];
|
||||
|
||||
// TODO: this can be made faster
|
||||
if ((this.critbits[ancestor] >> 8) > (critbit >> 8)) {
|
||||
continue;
|
||||
}
|
||||
else if ((this.critbits[ancestor] >> 8) === (critbit >> 8)) {
|
||||
if ((this.critbits[ancestor] & 0xff) < (critbit & 0xff))
|
||||
continue;
|
||||
}
|
||||
|
||||
best = i;
|
||||
break;
|
||||
}
|
||||
|
||||
// Do we need to attach to the root?
|
||||
if (best < 0) {
|
||||
this.root = internal + 1;
|
||||
|
||||
// Need to rewire parent as child?
|
||||
if (l > 0) {
|
||||
parent = ancestors[0];
|
||||
|
||||
opposite[internal] = parent + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Simple case without rotation
|
||||
else if (best === l - 1) {
|
||||
parent = ancestors[best];
|
||||
dir = path[best];
|
||||
|
||||
leftOrRight = dir === 0 ? this.lefts : this.rights;
|
||||
|
||||
leftOrRight[parent] = internal + 1;
|
||||
}
|
||||
|
||||
// Full rotation
|
||||
else {
|
||||
parent = ancestors[best];
|
||||
dir = path[best];
|
||||
child = ancestors[best + 1];
|
||||
|
||||
opposite[internal] = child + 1;
|
||||
|
||||
leftOrRight = dir === 0 ? this.lefts : this.rights;
|
||||
|
||||
leftOrRight[parent] = internal + 1;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the value attached to the given key in the tree or
|
||||
* undefined if not found.
|
||||
*
|
||||
* @param {string} key - Key to get.
|
||||
* @return {any}
|
||||
*/
|
||||
FixedCritBitTreeMap.prototype.get = function(key) {
|
||||
|
||||
// Walk state
|
||||
var pointer = this.root,
|
||||
dir;
|
||||
|
||||
// Walking the tree
|
||||
while (true) {
|
||||
|
||||
// Dead end
|
||||
if (pointer === 0)
|
||||
return;
|
||||
|
||||
// Traversing an internal node
|
||||
if (pointer > 0) {
|
||||
pointer -= 1;
|
||||
dir = getDirection(key, this.critbits[pointer]);
|
||||
|
||||
pointer = dir === 0 ? this.lefts[pointer] : this.rights[pointer];
|
||||
}
|
||||
|
||||
// Reaching an external node
|
||||
else {
|
||||
pointer = -pointer;
|
||||
pointer -= 1;
|
||||
|
||||
if (this.keys[pointer] !== key)
|
||||
return;
|
||||
|
||||
return this.values[pointer];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to return whether the given key exists in the tree.
|
||||
*
|
||||
* @param {string} key - Key to test.
|
||||
* @return {boolean}
|
||||
*/
|
||||
FixedCritBitTreeMap.prototype.has = function(key) {
|
||||
|
||||
// Walk state
|
||||
var pointer = this.root,
|
||||
dir;
|
||||
|
||||
// Walking the tree
|
||||
while (true) {
|
||||
|
||||
// Dead end
|
||||
if (pointer === 0)
|
||||
return false;
|
||||
|
||||
// Traversing an internal node
|
||||
if (pointer > 0) {
|
||||
pointer -= 1;
|
||||
dir = getDirection(key, this.critbits[pointer]);
|
||||
|
||||
pointer = dir === 0 ? this.lefts[pointer] : this.rights[pointer];
|
||||
}
|
||||
|
||||
// Reaching an external node
|
||||
else {
|
||||
pointer = -pointer;
|
||||
pointer -= 1;
|
||||
|
||||
return this.keys[pointer] === key;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the tree in key order.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
FixedCritBitTreeMap.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
// Inorder traversal of the tree
|
||||
var current = this.root,
|
||||
stack = [],
|
||||
p;
|
||||
|
||||
while (true) {
|
||||
|
||||
if (current !== 0) {
|
||||
stack.push(current);
|
||||
|
||||
current = current > 0 ? this.lefts[current - 1] : 0;
|
||||
}
|
||||
|
||||
else {
|
||||
if (stack.length > 0) {
|
||||
current = stack.pop();
|
||||
|
||||
if (current < 0) {
|
||||
p = -current;
|
||||
p -= 1;
|
||||
|
||||
callback.call(scope, this.values[p], this.keys[p]);
|
||||
}
|
||||
|
||||
current = current > 0 ? this.rights[current - 1] : 0;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
FixedCritBitTreeMap.prototype.inspect = function() {
|
||||
return this;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
FixedCritBitTreeMap.prototype[Symbol.for('nodejs.util.inspect.custom')] = FixedCritBitTreeMap.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a FixedCritBitTreeMap.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @return {FixedCritBitTreeMap}
|
||||
*/
|
||||
// FixedCritBitTreeMap.from = function(iterable) {
|
||||
|
||||
// };
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = FixedCritBitTreeMap;
|
||||
34
backend/node_modules/mnemonist/fixed-deque.d.ts
generated
vendored
Normal file
34
backend/node_modules/mnemonist/fixed-deque.d.ts
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Mnemonist FixedDeque Typings
|
||||
* =============================
|
||||
*/
|
||||
import {IArrayLikeConstructor, TypedArray} from './utils/types';
|
||||
|
||||
export default class FixedDeque<T> implements Iterable<T> {
|
||||
|
||||
// Members
|
||||
capacity: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(ArrayClass: IArrayLikeConstructor, capacity: number);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
push(item: T): number;
|
||||
unshift(item: T): number;
|
||||
pop(): T | undefined;
|
||||
shift(): T | undefined;
|
||||
peekFirst(): T | undefined;
|
||||
peekLast(): T | undefined;
|
||||
get(index: number): T | undefined;
|
||||
forEach(callback: (item: T, index: number, buffer: this) => void, scope?: any): void;
|
||||
toArray(): Array<T> | TypedArray;
|
||||
values(): IterableIterator<T>;
|
||||
entries(): IterableIterator<[number, T]>;
|
||||
[Symbol.iterator](): IterableIterator<T>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(iterable: Iterable<I> | {[key: string]: I}, ArrayClass: IArrayLikeConstructor, capacity?: number): FixedDeque<I>;
|
||||
}
|
||||
351
backend/node_modules/mnemonist/fixed-deque.js
generated
vendored
Normal file
351
backend/node_modules/mnemonist/fixed-deque.js
generated
vendored
Normal file
@@ -0,0 +1,351 @@
|
||||
/**
|
||||
* Mnemonist FixedDeque
|
||||
* =====================
|
||||
*
|
||||
* Fixed capacity double-ended queue implemented as ring deque.
|
||||
*/
|
||||
var iterables = require('./utils/iterables.js'),
|
||||
Iterator = require('obliterator/iterator');
|
||||
|
||||
/**
|
||||
* FixedDeque.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function FixedDeque(ArrayClass, capacity) {
|
||||
|
||||
if (arguments.length < 2)
|
||||
throw new Error('mnemonist/fixed-deque: expecting an Array class and a capacity.');
|
||||
|
||||
if (typeof capacity !== 'number' || capacity <= 0)
|
||||
throw new Error('mnemonist/fixed-deque: `capacity` should be a positive number.');
|
||||
|
||||
this.ArrayClass = ArrayClass;
|
||||
this.capacity = capacity;
|
||||
this.items = new ArrayClass(this.capacity);
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
FixedDeque.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.start = 0;
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to append a value to the deque.
|
||||
*
|
||||
* @param {any} item - Item to append.
|
||||
* @return {number} - Returns the new size of the deque.
|
||||
*/
|
||||
FixedDeque.prototype.push = function(item) {
|
||||
if (this.size === this.capacity)
|
||||
throw new Error('mnemonist/fixed-deque.push: deque capacity (' + this.capacity + ') exceeded!');
|
||||
|
||||
var index = (this.start + this.size) % this.capacity;
|
||||
|
||||
this.items[index] = item;
|
||||
|
||||
return ++this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to prepend a value to the deque.
|
||||
*
|
||||
* @param {any} item - Item to prepend.
|
||||
* @return {number} - Returns the new size of the deque.
|
||||
*/
|
||||
FixedDeque.prototype.unshift = function(item) {
|
||||
if (this.size === this.capacity)
|
||||
throw new Error('mnemonist/fixed-deque.unshift: deque capacity (' + this.capacity + ') exceeded!');
|
||||
|
||||
var index = this.start - 1;
|
||||
|
||||
if (this.start === 0)
|
||||
index = this.capacity - 1;
|
||||
|
||||
this.items[index] = item;
|
||||
this.start = index;
|
||||
|
||||
return ++this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to pop the deque.
|
||||
*
|
||||
* @return {any} - Returns the popped item.
|
||||
*/
|
||||
FixedDeque.prototype.pop = function() {
|
||||
if (this.size === 0)
|
||||
return;
|
||||
|
||||
const index = (this.start + this.size - 1) % this.capacity;
|
||||
|
||||
this.size--;
|
||||
|
||||
return this.items[index];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to shift the deque.
|
||||
*
|
||||
* @return {any} - Returns the shifted item.
|
||||
*/
|
||||
FixedDeque.prototype.shift = function() {
|
||||
if (this.size === 0)
|
||||
return;
|
||||
|
||||
var index = this.start;
|
||||
|
||||
this.size--;
|
||||
this.start++;
|
||||
|
||||
if (this.start === this.capacity)
|
||||
this.start = 0;
|
||||
|
||||
return this.items[index];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to peek the first value of the deque.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
FixedDeque.prototype.peekFirst = function() {
|
||||
if (this.size === 0)
|
||||
return;
|
||||
|
||||
return this.items[this.start];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to peek the last value of the deque.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
FixedDeque.prototype.peekLast = function() {
|
||||
if (this.size === 0)
|
||||
return;
|
||||
|
||||
var index = this.start + this.size - 1;
|
||||
|
||||
if (index > this.capacity)
|
||||
index -= this.capacity;
|
||||
|
||||
return this.items[index];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the desired value of the deque.
|
||||
*
|
||||
* @param {number} index
|
||||
* @return {any}
|
||||
*/
|
||||
FixedDeque.prototype.get = function(index) {
|
||||
if (this.size === 0)
|
||||
return;
|
||||
|
||||
index = this.start + index;
|
||||
|
||||
if (index > this.capacity)
|
||||
index -= this.capacity;
|
||||
|
||||
return this.items[index];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the deque.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
FixedDeque.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
var c = this.capacity,
|
||||
l = this.size,
|
||||
i = this.start,
|
||||
j = 0;
|
||||
|
||||
while (j < l) {
|
||||
callback.call(scope, this.items[i], j, this);
|
||||
i++;
|
||||
j++;
|
||||
|
||||
if (i === c)
|
||||
i = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to convert the deque to a JavaScript array.
|
||||
*
|
||||
* @return {array}
|
||||
*/
|
||||
// TODO: optional array class as argument?
|
||||
FixedDeque.prototype.toArray = function() {
|
||||
|
||||
// Optimization
|
||||
var offset = this.start + this.size;
|
||||
|
||||
if (offset < this.capacity)
|
||||
return this.items.slice(this.start, offset);
|
||||
|
||||
var array = new this.ArrayClass(this.size),
|
||||
c = this.capacity,
|
||||
l = this.size,
|
||||
i = this.start,
|
||||
j = 0;
|
||||
|
||||
while (j < l) {
|
||||
array[j] = this.items[i];
|
||||
i++;
|
||||
j++;
|
||||
|
||||
if (i === c)
|
||||
i = 0;
|
||||
}
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over the deque's values.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
FixedDeque.prototype.values = function() {
|
||||
var items = this.items,
|
||||
c = this.capacity,
|
||||
l = this.size,
|
||||
i = this.start,
|
||||
j = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (j >= l)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
var value = items[i];
|
||||
|
||||
i++;
|
||||
j++;
|
||||
|
||||
if (i === c)
|
||||
i = 0;
|
||||
|
||||
return {
|
||||
value: value,
|
||||
done: false
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over the deque's entries.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
FixedDeque.prototype.entries = function() {
|
||||
var items = this.items,
|
||||
c = this.capacity,
|
||||
l = this.size,
|
||||
i = this.start,
|
||||
j = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (j >= l)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
var value = items[i];
|
||||
|
||||
i++;
|
||||
|
||||
if (i === c)
|
||||
i = 0;
|
||||
|
||||
return {
|
||||
value: [j++, value],
|
||||
done: false
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.values method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
FixedDeque.prototype[Symbol.iterator] = FixedDeque.prototype.values;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
FixedDeque.prototype.inspect = function() {
|
||||
var array = this.toArray();
|
||||
|
||||
array.type = this.ArrayClass.name;
|
||||
array.capacity = this.capacity;
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(array, 'constructor', {
|
||||
value: FixedDeque,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
FixedDeque.prototype[Symbol.for('nodejs.util.inspect.custom')] = FixedDeque.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a deque.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {function} ArrayClass - Array class to use.
|
||||
* @param {number} capacity - Desired capacity.
|
||||
* @return {FiniteStack}
|
||||
*/
|
||||
FixedDeque.from = function(iterable, ArrayClass, capacity) {
|
||||
if (arguments.length < 3) {
|
||||
capacity = iterables.guessLength(iterable);
|
||||
|
||||
if (typeof capacity !== 'number')
|
||||
throw new Error('mnemonist/fixed-deque.from: could not guess iterable length. Please provide desired capacity as last argument.');
|
||||
}
|
||||
|
||||
var deque = new FixedDeque(ArrayClass, capacity);
|
||||
|
||||
if (iterables.isArrayLike(iterable)) {
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = iterable.length; i < l; i++)
|
||||
deque.items[i] = iterable[i];
|
||||
|
||||
deque.size = l;
|
||||
|
||||
return deque;
|
||||
}
|
||||
|
||||
iterables.forEach(iterable, function(value) {
|
||||
deque.push(value);
|
||||
});
|
||||
|
||||
return deque;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = FixedDeque;
|
||||
25
backend/node_modules/mnemonist/fixed-reverse-heap.d.ts
generated
vendored
Normal file
25
backend/node_modules/mnemonist/fixed-reverse-heap.d.ts
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Mnemonist FixedReverseHeap Typings
|
||||
* ===================================
|
||||
*/
|
||||
import {IArrayLikeConstructor, TypedArray} from './utils/types';
|
||||
|
||||
type HeapComparator<T> = (a: T, b: T) => number;
|
||||
|
||||
export default class FixedReverseHeap<T> {
|
||||
|
||||
// Members
|
||||
capacity: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(ArrayClass: IArrayLikeConstructor, comparator: HeapComparator<T>, capacity: number);
|
||||
constructor(ArrayClass: IArrayLikeConstructor, capacity: number);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
push(item: T): number;
|
||||
consume(): Array<T> | TypedArray;
|
||||
toArray(): Array<T> | TypedArray;
|
||||
inspect(): any;
|
||||
}
|
||||
209
backend/node_modules/mnemonist/fixed-reverse-heap.js
generated
vendored
Normal file
209
backend/node_modules/mnemonist/fixed-reverse-heap.js
generated
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* Mnemonist Fixed Reverse Heap
|
||||
* =============================
|
||||
*
|
||||
* Static heap implementation with fixed capacity. It's a "reverse" heap
|
||||
* because it stores the elements in reverse so we can replace the worst
|
||||
* item in logarithmic time. As such, one cannot pop this heap but can only
|
||||
* consume it at the end. This structure is very efficient when trying to
|
||||
* find the n smallest/largest items from a larger query (k nearest neigbors
|
||||
* for instance).
|
||||
*/
|
||||
var comparators = require('./utils/comparators.js'),
|
||||
Heap = require('./heap.js');
|
||||
|
||||
var DEFAULT_COMPARATOR = comparators.DEFAULT_COMPARATOR,
|
||||
reverseComparator = comparators.reverseComparator;
|
||||
|
||||
/**
|
||||
* Helper functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Function used to sift up.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @param {number} size - Heap's true size.
|
||||
* @param {number} i - Index.
|
||||
*/
|
||||
function siftUp(compare, heap, size, i) {
|
||||
var endIndex = size,
|
||||
startIndex = i,
|
||||
item = heap[i],
|
||||
childIndex = 2 * i + 1,
|
||||
rightIndex;
|
||||
|
||||
while (childIndex < endIndex) {
|
||||
rightIndex = childIndex + 1;
|
||||
|
||||
if (
|
||||
rightIndex < endIndex &&
|
||||
compare(heap[childIndex], heap[rightIndex]) >= 0
|
||||
) {
|
||||
childIndex = rightIndex;
|
||||
}
|
||||
|
||||
heap[i] = heap[childIndex];
|
||||
i = childIndex;
|
||||
childIndex = 2 * i + 1;
|
||||
}
|
||||
|
||||
heap[i] = item;
|
||||
Heap.siftDown(compare, heap, startIndex, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fully consumes the given heap.
|
||||
*
|
||||
* @param {function} ArrayClass - Array class to use.
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @param {number} size - True size of the heap.
|
||||
* @return {array}
|
||||
*/
|
||||
function consume(ArrayClass, compare, heap, size) {
|
||||
var l = size,
|
||||
i = l;
|
||||
|
||||
var array = new ArrayClass(size),
|
||||
lastItem,
|
||||
item;
|
||||
|
||||
while (i > 0) {
|
||||
lastItem = heap[--i];
|
||||
|
||||
if (i !== 0) {
|
||||
item = heap[0];
|
||||
heap[0] = lastItem;
|
||||
siftUp(compare, heap, --size, 0);
|
||||
lastItem = item;
|
||||
}
|
||||
|
||||
array[i] = lastItem;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binary Minimum FixedReverseHeap.
|
||||
*
|
||||
* @constructor
|
||||
* @param {function} ArrayClass - The class of array to use.
|
||||
* @param {function} comparator - Comparator function.
|
||||
* @param {number} capacity - Maximum number of items to keep.
|
||||
*/
|
||||
function FixedReverseHeap(ArrayClass, comparator, capacity) {
|
||||
|
||||
// Comparator can be omitted
|
||||
if (arguments.length === 2) {
|
||||
capacity = comparator;
|
||||
comparator = null;
|
||||
}
|
||||
|
||||
this.ArrayClass = ArrayClass;
|
||||
this.capacity = capacity;
|
||||
|
||||
this.items = new ArrayClass(capacity);
|
||||
this.clear();
|
||||
this.comparator = comparator || DEFAULT_COMPARATOR;
|
||||
|
||||
if (typeof capacity !== 'number' && capacity <= 0)
|
||||
throw new Error('mnemonist/FixedReverseHeap.constructor: capacity should be a number > 0.');
|
||||
|
||||
if (typeof this.comparator !== 'function')
|
||||
throw new Error('mnemonist/FixedReverseHeap.constructor: given comparator should be a function.');
|
||||
|
||||
this.comparator = reverseComparator(this.comparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the heap.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
FixedReverseHeap.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to push an item into the heap.
|
||||
*
|
||||
* @param {any} item - Item to push.
|
||||
* @return {number}
|
||||
*/
|
||||
FixedReverseHeap.prototype.push = function(item) {
|
||||
|
||||
// Still some place
|
||||
if (this.size < this.capacity) {
|
||||
this.items[this.size] = item;
|
||||
Heap.siftDown(this.comparator, this.items, 0, this.size);
|
||||
this.size++;
|
||||
}
|
||||
|
||||
// Heap is full, we need to replace worst item
|
||||
else {
|
||||
|
||||
if (this.comparator(item, this.items[0]) > 0)
|
||||
Heap.replace(this.comparator, this.items, item);
|
||||
}
|
||||
|
||||
return this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to peek the worst item in the heap.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
FixedReverseHeap.prototype.peek = function() {
|
||||
return this.items[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to consume the heap fully and return its items as a sorted array.
|
||||
*
|
||||
* @return {array}
|
||||
*/
|
||||
FixedReverseHeap.prototype.consume = function() {
|
||||
var items = consume(this.ArrayClass, this.comparator, this.items, this.size);
|
||||
this.size = 0;
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to convert the heap to an array. Note that it basically clone
|
||||
* the heap and consumes it completely. This is hardly performant.
|
||||
*
|
||||
* @return {array}
|
||||
*/
|
||||
FixedReverseHeap.prototype.toArray = function() {
|
||||
return consume(this.ArrayClass, this.comparator, this.items.slice(0, this.size), this.size);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
FixedReverseHeap.prototype.inspect = function() {
|
||||
var proxy = this.toArray();
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: FixedReverseHeap,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
FixedReverseHeap.prototype[Symbol.for('nodejs.util.inspect.custom')] = FixedReverseHeap.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = FixedReverseHeap;
|
||||
36
backend/node_modules/mnemonist/fixed-stack.d.ts
generated
vendored
Normal file
36
backend/node_modules/mnemonist/fixed-stack.d.ts
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Mnemonist FixedStack Typings
|
||||
* =============================
|
||||
*/
|
||||
import {IArrayLikeConstructor, TypedArray} from './utils/types';
|
||||
|
||||
export default class FixedStack<T> implements Iterable<T> {
|
||||
|
||||
// Members
|
||||
capacity: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(ArrayClass: IArrayLikeConstructor, capacity: number);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
push(item: T): number;
|
||||
pop(): T | undefined;
|
||||
peek(): T | undefined;
|
||||
forEach(callback: (item: T, index: number, stack: this) => void, scope?: any): void;
|
||||
toArray(): Array<T> | TypedArray;
|
||||
values(): IterableIterator<T>;
|
||||
entries(): IterableIterator<[number, T]>;
|
||||
[Symbol.iterator](): IterableIterator<T>;
|
||||
toString(): string;
|
||||
toJSON(): Iterable<T>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(
|
||||
iterable: Iterable<I> | {[key: string]: I},
|
||||
ArrayClass: IArrayLikeConstructor,
|
||||
capacity?: number
|
||||
): FixedStack<I>;
|
||||
}
|
||||
242
backend/node_modules/mnemonist/fixed-stack.js
generated
vendored
Normal file
242
backend/node_modules/mnemonist/fixed-stack.js
generated
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
/**
|
||||
* Mnemonist FixedStack
|
||||
* =====================
|
||||
*
|
||||
* The fixed stack is a stack whose capacity is defined beforehand and that
|
||||
* cannot be exceeded. This class is really useful when combined with
|
||||
* byte arrays to save up some memory and avoid memory re-allocation, hence
|
||||
* speeding up computations.
|
||||
*
|
||||
* This has however a downside: you need to know the maximum size you stack
|
||||
* can have during your iteration (which is not too difficult to compute when
|
||||
* performing, say, a DFS on a balanced binary tree).
|
||||
*/
|
||||
var Iterator = require('obliterator/iterator'),
|
||||
iterables = require('./utils/iterables.js');
|
||||
|
||||
/**
|
||||
* FixedStack
|
||||
*
|
||||
* @constructor
|
||||
* @param {function} ArrayClass - Array class to use.
|
||||
* @param {number} capacity - Desired capacity.
|
||||
*/
|
||||
function FixedStack(ArrayClass, capacity) {
|
||||
|
||||
if (arguments.length < 2)
|
||||
throw new Error('mnemonist/fixed-stack: expecting an Array class and a capacity.');
|
||||
|
||||
if (typeof capacity !== 'number' || capacity <= 0)
|
||||
throw new Error('mnemonist/fixed-stack: `capacity` should be a positive number.');
|
||||
|
||||
this.capacity = capacity;
|
||||
this.ArrayClass = ArrayClass;
|
||||
this.items = new this.ArrayClass(this.capacity);
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the stack.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
FixedStack.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add an item to the stack.
|
||||
*
|
||||
* @param {any} item - Item to add.
|
||||
* @return {number}
|
||||
*/
|
||||
FixedStack.prototype.push = function(item) {
|
||||
if (this.size === this.capacity)
|
||||
throw new Error('mnemonist/fixed-stack.push: stack capacity (' + this.capacity + ') exceeded!');
|
||||
|
||||
this.items[this.size++] = item;
|
||||
return this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to retrieve & remove the last item of the stack.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
FixedStack.prototype.pop = function() {
|
||||
if (this.size === 0)
|
||||
return;
|
||||
|
||||
return this.items[--this.size];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the last item of the stack.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
FixedStack.prototype.peek = function() {
|
||||
return this.items[this.size - 1];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the stack.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
FixedStack.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
for (var i = 0, l = this.items.length; i < l; i++)
|
||||
callback.call(scope, this.items[l - i - 1], i, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to convert the stack to a JavaScript array.
|
||||
*
|
||||
* @return {array}
|
||||
*/
|
||||
FixedStack.prototype.toArray = function() {
|
||||
var array = new this.ArrayClass(this.size),
|
||||
l = this.size - 1,
|
||||
i = this.size;
|
||||
|
||||
while (i--)
|
||||
array[i] = this.items[l - i];
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a stack's values.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
FixedStack.prototype.values = function() {
|
||||
var items = this.items,
|
||||
l = this.size,
|
||||
i = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= l)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
var value = items[l - i - 1];
|
||||
i++;
|
||||
|
||||
return {
|
||||
value: value,
|
||||
done: false
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a stack's entries.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
FixedStack.prototype.entries = function() {
|
||||
var items = this.items,
|
||||
l = this.size,
|
||||
i = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= l)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
var value = items[l - i - 1];
|
||||
|
||||
return {
|
||||
value: [i++, value],
|
||||
done: false
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.values method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
FixedStack.prototype[Symbol.iterator] = FixedStack.prototype.values;
|
||||
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
FixedStack.prototype.toString = function() {
|
||||
return this.toArray().join(',');
|
||||
};
|
||||
|
||||
FixedStack.prototype.toJSON = function() {
|
||||
return this.toArray();
|
||||
};
|
||||
|
||||
FixedStack.prototype.inspect = function() {
|
||||
var array = this.toArray();
|
||||
|
||||
array.type = this.ArrayClass.name;
|
||||
array.capacity = this.capacity;
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(array, 'constructor', {
|
||||
value: FixedStack,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
FixedStack.prototype[Symbol.for('nodejs.util.inspect.custom')] = FixedStack.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a stack.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {function} ArrayClass - Array class to use.
|
||||
* @param {number} capacity - Desired capacity.
|
||||
* @return {FixedStack}
|
||||
*/
|
||||
FixedStack.from = function(iterable, ArrayClass, capacity) {
|
||||
|
||||
if (arguments.length < 3) {
|
||||
capacity = iterables.guessLength(iterable);
|
||||
|
||||
if (typeof capacity !== 'number')
|
||||
throw new Error('mnemonist/fixed-stack.from: could not guess iterable length. Please provide desired capacity as last argument.');
|
||||
}
|
||||
|
||||
var stack = new FixedStack(ArrayClass, capacity);
|
||||
|
||||
if (iterables.isArrayLike(iterable)) {
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = iterable.length; i < l; i++)
|
||||
stack.items[i] = iterable[i];
|
||||
|
||||
stack.size = l;
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
iterables.forEach(iterable, function(value) {
|
||||
stack.push(value);
|
||||
});
|
||||
|
||||
return stack;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = FixedStack;
|
||||
33
backend/node_modules/mnemonist/fuzzy-map.d.ts
generated
vendored
Normal file
33
backend/node_modules/mnemonist/fuzzy-map.d.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Mnemonist FuzzyMap Typings
|
||||
* ==========================
|
||||
*/
|
||||
type HashFunction<K> = (key: any) => K;
|
||||
type HashFunctionsTuple<K> = [HashFunction<K>, HashFunction<K>];
|
||||
|
||||
export default class FuzzyMap<K, V> implements Iterable<V> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(hashFunction: HashFunction<K>);
|
||||
constructor(hashFunctionsTuple: HashFunctionsTuple<K>);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
add(key: V): this;
|
||||
set(key: K, value: V): this;
|
||||
get(key: any): V | undefined;
|
||||
has(key: any): boolean;
|
||||
forEach(callback: (value: V, key: V) => void, scope?: this): void;
|
||||
values(): IterableIterator<V>;
|
||||
[Symbol.iterator](): IterableIterator<V>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I, J>(
|
||||
iterable: Iterable<[I, J]> | {[key: string]: J},
|
||||
hashFunction: HashFunction<I> | HashFunctionsTuple<I>,
|
||||
): FuzzyMap<I, J>;
|
||||
}
|
||||
185
backend/node_modules/mnemonist/fuzzy-map.js
generated
vendored
Normal file
185
backend/node_modules/mnemonist/fuzzy-map.js
generated
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
* Mnemonist Fuzzy Map
|
||||
* ====================
|
||||
*
|
||||
* The fuzzy map is a map whose keys are processed by a function before
|
||||
* read/write operations. This can often result in multiple keys accessing
|
||||
* the same resource (example: a map with lowercased keys).
|
||||
*/
|
||||
var forEach = require('obliterator/foreach');
|
||||
|
||||
var identity = function(x) {
|
||||
return x;
|
||||
};
|
||||
|
||||
/**
|
||||
* FuzzyMap.
|
||||
*
|
||||
* @constructor
|
||||
* @param {array|function} descriptor - Hash functions descriptor.
|
||||
*/
|
||||
function FuzzyMap(descriptor) {
|
||||
this.items = new Map();
|
||||
this.clear();
|
||||
|
||||
if (Array.isArray(descriptor)) {
|
||||
this.writeHashFunction = descriptor[0];
|
||||
this.readHashFunction = descriptor[1];
|
||||
}
|
||||
else {
|
||||
this.writeHashFunction = descriptor;
|
||||
this.readHashFunction = descriptor;
|
||||
}
|
||||
|
||||
if (!this.writeHashFunction)
|
||||
this.writeHashFunction = identity;
|
||||
if (!this.readHashFunction)
|
||||
this.readHashFunction = identity;
|
||||
|
||||
if (typeof this.writeHashFunction !== 'function')
|
||||
throw new Error('mnemonist/FuzzyMap.constructor: invalid hash function given.');
|
||||
|
||||
if (typeof this.readHashFunction !== 'function')
|
||||
throw new Error('mnemonist/FuzzyMap.constructor: invalid hash function given.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
FuzzyMap.prototype.clear = function() {
|
||||
this.items.clear();
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add an item to the FuzzyMap.
|
||||
*
|
||||
* @param {any} item - Item to add.
|
||||
* @return {FuzzyMap}
|
||||
*/
|
||||
FuzzyMap.prototype.add = function(item) {
|
||||
var key = this.writeHashFunction(item);
|
||||
|
||||
this.items.set(key, item);
|
||||
this.size = this.items.size;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set an item in the FuzzyMap using the given key.
|
||||
*
|
||||
* @param {any} key - Key to use.
|
||||
* @param {any} item - Item to add.
|
||||
* @return {FuzzyMap}
|
||||
*/
|
||||
FuzzyMap.prototype.set = function(key, item) {
|
||||
key = this.writeHashFunction(key);
|
||||
|
||||
this.items.set(key, item);
|
||||
this.size = this.items.size;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to retrieve an item from the FuzzyMap.
|
||||
*
|
||||
* @param {any} key - Key to use.
|
||||
* @return {any}
|
||||
*/
|
||||
FuzzyMap.prototype.get = function(key) {
|
||||
key = this.readHashFunction(key);
|
||||
|
||||
return this.items.get(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to test the existence of an item in the map.
|
||||
*
|
||||
* @param {any} key - Key to check.
|
||||
* @return {boolean}
|
||||
*/
|
||||
FuzzyMap.prototype.has = function(key) {
|
||||
key = this.readHashFunction(key);
|
||||
|
||||
return this.items.has(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over each of the FuzzyMap's values.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
FuzzyMap.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
this.items.forEach(function(value) {
|
||||
callback.call(scope, value, value);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the FuzzyMap's values.
|
||||
*
|
||||
* @return {FuzzyMapIterator}
|
||||
*/
|
||||
FuzzyMap.prototype.values = function() {
|
||||
return this.items.values();
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.values method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
FuzzyMap.prototype[Symbol.iterator] = FuzzyMap.prototype.values;
|
||||
|
||||
/**
|
||||
* Convenience known method.
|
||||
*/
|
||||
FuzzyMap.prototype.inspect = function() {
|
||||
var array = Array.from(this.items.values());
|
||||
|
||||
Object.defineProperty(array, 'constructor', {
|
||||
value: FuzzyMap,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
FuzzyMap.prototype[Symbol.for('nodejs.util.inspect.custom')] = FuzzyMap.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a structure.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {array|function} descriptor - Hash functions descriptor.
|
||||
* @param {boolean} useSet - Whether to use #.set or #.add
|
||||
* @return {FuzzyMap}
|
||||
*/
|
||||
FuzzyMap.from = function(iterable, descriptor, useSet) {
|
||||
var map = new FuzzyMap(descriptor);
|
||||
|
||||
forEach(iterable, function(value, key) {
|
||||
if (useSet)
|
||||
map.set(key, value);
|
||||
else
|
||||
map.add(value);
|
||||
});
|
||||
|
||||
return map;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = FuzzyMap;
|
||||
36
backend/node_modules/mnemonist/fuzzy-multi-map.d.ts
generated
vendored
Normal file
36
backend/node_modules/mnemonist/fuzzy-multi-map.d.ts
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Mnemonist FuzzyMultiMap Typings
|
||||
* ================================
|
||||
*/
|
||||
type HashFunction<K> = (key: any) => K;
|
||||
type HashFunctionsTuple<K> = [HashFunction<K>, HashFunction<K>];
|
||||
type FuzzyMultiMapContainer = ArrayConstructor | SetConstructor;
|
||||
|
||||
export default class FuzzyMultiMap<K, V> implements Iterable<V> {
|
||||
|
||||
// Members
|
||||
dimension: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(hashFunction: HashFunction<K>, Container?: FuzzyMultiMapContainer);
|
||||
constructor(hashFunctions: HashFunctionsTuple<K>, Container?: FuzzyMultiMapContainer);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
add(value: V): this;
|
||||
set(key: K, value: V): this;
|
||||
get(key: any): Array<V> | Set<V> | undefined;
|
||||
has(key: any): boolean;
|
||||
forEach(callback: (value: V, key: V) => void, scope?: any): void;
|
||||
values(): IterableIterator<V>;
|
||||
[Symbol.iterator](): IterableIterator<V>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I, J>(
|
||||
iterable: Iterable<[I, J]> | {[key: string]: J},
|
||||
hashFunction: HashFunction<I> | HashFunctionsTuple<I>,
|
||||
Container?: FuzzyMultiMapContainer
|
||||
): FuzzyMultiMap<I, J>;
|
||||
}
|
||||
196
backend/node_modules/mnemonist/fuzzy-multi-map.js
generated
vendored
Normal file
196
backend/node_modules/mnemonist/fuzzy-multi-map.js
generated
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
/**
|
||||
* Mnemonist FuzzyMultiMap
|
||||
* ========================
|
||||
*
|
||||
* Same as the fuzzy map but relying on a MultiMap rather than a Map.
|
||||
*/
|
||||
var MultiMap = require('./multi-map.js'),
|
||||
forEach = require('obliterator/foreach');
|
||||
|
||||
var identity = function(x) {
|
||||
return x;
|
||||
};
|
||||
|
||||
/**
|
||||
* FuzzyMultiMap.
|
||||
*
|
||||
* @constructor
|
||||
* @param {array|function} descriptor - Hash functions descriptor.
|
||||
* @param {function} Container - Container to use.
|
||||
*/
|
||||
function FuzzyMultiMap(descriptor, Container) {
|
||||
this.items = new MultiMap(Container);
|
||||
this.clear();
|
||||
|
||||
if (Array.isArray(descriptor)) {
|
||||
this.writeHashFunction = descriptor[0];
|
||||
this.readHashFunction = descriptor[1];
|
||||
}
|
||||
else {
|
||||
this.writeHashFunction = descriptor;
|
||||
this.readHashFunction = descriptor;
|
||||
}
|
||||
|
||||
if (!this.writeHashFunction)
|
||||
this.writeHashFunction = identity;
|
||||
if (!this.readHashFunction)
|
||||
this.readHashFunction = identity;
|
||||
|
||||
if (typeof this.writeHashFunction !== 'function')
|
||||
throw new Error('mnemonist/FuzzyMultiMap.constructor: invalid hash function given.');
|
||||
|
||||
if (typeof this.readHashFunction !== 'function')
|
||||
throw new Error('mnemonist/FuzzyMultiMap.constructor: invalid hash function given.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
FuzzyMultiMap.prototype.clear = function() {
|
||||
this.items.clear();
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
this.dimension = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add an item to the index.
|
||||
*
|
||||
* @param {any} item - Item to add.
|
||||
* @return {FuzzyMultiMap}
|
||||
*/
|
||||
FuzzyMultiMap.prototype.add = function(item) {
|
||||
var key = this.writeHashFunction(item);
|
||||
|
||||
this.items.set(key, item);
|
||||
this.size = this.items.size;
|
||||
this.dimension = this.items.dimension;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set an item in the index using the given key.
|
||||
*
|
||||
* @param {any} key - Key to use.
|
||||
* @param {any} item - Item to add.
|
||||
* @return {FuzzyMultiMap}
|
||||
*/
|
||||
FuzzyMultiMap.prototype.set = function(key, item) {
|
||||
key = this.writeHashFunction(key);
|
||||
|
||||
this.items.set(key, item);
|
||||
this.size = this.items.size;
|
||||
this.dimension = this.items.dimension;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to retrieve an item from the index.
|
||||
*
|
||||
* @param {any} key - Key to use.
|
||||
* @return {any}
|
||||
*/
|
||||
FuzzyMultiMap.prototype.get = function(key) {
|
||||
key = this.readHashFunction(key);
|
||||
|
||||
return this.items.get(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to test the existence of an item in the map.
|
||||
*
|
||||
* @param {any} key - Key to check.
|
||||
* @return {boolean}
|
||||
*/
|
||||
FuzzyMultiMap.prototype.has = function(key) {
|
||||
key = this.readHashFunction(key);
|
||||
|
||||
return this.items.has(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over each of the index's values.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
FuzzyMultiMap.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
this.items.forEach(function(value) {
|
||||
callback.call(scope, value, value);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the index's values.
|
||||
*
|
||||
* @return {FuzzyMultiMapIterator}
|
||||
*/
|
||||
FuzzyMultiMap.prototype.values = function() {
|
||||
return this.items.values();
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.values method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
FuzzyMultiMap.prototype[Symbol.iterator] = FuzzyMultiMap.prototype.values;
|
||||
|
||||
/**
|
||||
* Convenience known method.
|
||||
*/
|
||||
FuzzyMultiMap.prototype.inspect = function() {
|
||||
var array = Array.from(this);
|
||||
|
||||
Object.defineProperty(array, 'constructor', {
|
||||
value: FuzzyMultiMap,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
FuzzyMultiMap.prototype[Symbol.for('nodejs.util.inspect.custom')] = FuzzyMultiMap.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a structure.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {array|function} descriptor - Hash functions descriptor.
|
||||
* @param {function} Container - Container to use.
|
||||
* @param {boolean} useSet - Whether to use #.set or #.add
|
||||
* @return {FuzzyMultiMap}
|
||||
*/
|
||||
FuzzyMultiMap.from = function(iterable, descriptor, Container, useSet) {
|
||||
if (arguments.length === 3) {
|
||||
if (typeof Container === 'boolean') {
|
||||
useSet = Container;
|
||||
Container = Array;
|
||||
}
|
||||
}
|
||||
|
||||
var map = new FuzzyMultiMap(descriptor, Container);
|
||||
|
||||
forEach(iterable, function(value, key) {
|
||||
if (useSet)
|
||||
map.set(key, value);
|
||||
else
|
||||
map.add(value);
|
||||
});
|
||||
|
||||
return map;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = FuzzyMultiMap;
|
||||
32
backend/node_modules/mnemonist/hashed-array-tree.d.ts
generated
vendored
Normal file
32
backend/node_modules/mnemonist/hashed-array-tree.d.ts
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Mnemonist HashedArrayTree Typings
|
||||
* ==================================
|
||||
*/
|
||||
import {IArrayLikeConstructor} from './utils/types';
|
||||
|
||||
type HashedArrayTreeOptions = {
|
||||
initialCapacity?: number;
|
||||
initialLength?: number;
|
||||
blockSize?: number;
|
||||
}
|
||||
|
||||
export default class HashedArrayTree<T> {
|
||||
|
||||
// Members
|
||||
blockSize: number;
|
||||
capacity: number;
|
||||
length: number;
|
||||
|
||||
// Constructor
|
||||
constructor(ArrayClass: IArrayLikeConstructor, capacity: number);
|
||||
constructor(ArrayClass: IArrayLikeConstructor, options: HashedArrayTreeOptions);
|
||||
|
||||
// Methods
|
||||
set(index: number, value: T): this;
|
||||
get(index: number): T | undefined;
|
||||
grow(capacity: number): this;
|
||||
resize(length: number): this;
|
||||
push(value: T): number;
|
||||
pop(): T | undefined;
|
||||
inspect(): any;
|
||||
}
|
||||
209
backend/node_modules/mnemonist/hashed-array-tree.js
generated
vendored
Normal file
209
backend/node_modules/mnemonist/hashed-array-tree.js
generated
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* Mnemonist HashedArrayTree
|
||||
* ==========================
|
||||
*
|
||||
* Abstract implementation of a hashed array tree representing arrays growing
|
||||
* dynamically.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defaults.
|
||||
*/
|
||||
var DEFAULT_BLOCK_SIZE = 1024;
|
||||
|
||||
/**
|
||||
* Helpers.
|
||||
*/
|
||||
function powerOfTwo(x) {
|
||||
return (x & (x - 1)) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* HashedArrayTree.
|
||||
*
|
||||
* @constructor
|
||||
* @param {function} ArrayClass - An array constructor.
|
||||
* @param {number|object} initialCapacityOrOptions - Self-explanatory.
|
||||
*/
|
||||
function HashedArrayTree(ArrayClass, initialCapacityOrOptions) {
|
||||
if (arguments.length < 1)
|
||||
throw new Error('mnemonist/hashed-array-tree: expecting at least a byte array constructor.');
|
||||
|
||||
var initialCapacity = initialCapacityOrOptions || 0,
|
||||
blockSize = DEFAULT_BLOCK_SIZE,
|
||||
initialLength = 0;
|
||||
|
||||
if (typeof initialCapacityOrOptions === 'object') {
|
||||
initialCapacity = initialCapacityOrOptions.initialCapacity || 0;
|
||||
initialLength = initialCapacityOrOptions.initialLength || 0;
|
||||
blockSize = initialCapacityOrOptions.blockSize || DEFAULT_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
if (!blockSize || !powerOfTwo(blockSize))
|
||||
throw new Error('mnemonist/hashed-array-tree: block size should be a power of two.');
|
||||
|
||||
var capacity = Math.max(initialLength, initialCapacity),
|
||||
initialBlocks = Math.ceil(capacity / blockSize);
|
||||
|
||||
this.ArrayClass = ArrayClass;
|
||||
this.length = initialLength;
|
||||
this.capacity = initialBlocks * blockSize;
|
||||
this.blockSize = blockSize;
|
||||
this.offsetMask = blockSize - 1;
|
||||
this.blockMask = Math.log2(blockSize);
|
||||
|
||||
// Allocating initial blocks
|
||||
this.blocks = new Array(initialBlocks);
|
||||
|
||||
for (var i = 0; i < initialBlocks; i++)
|
||||
this.blocks[i] = new this.ArrayClass(this.blockSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to set a value.
|
||||
*
|
||||
* @param {number} index - Index to edit.
|
||||
* @param {any} value - Value.
|
||||
* @return {HashedArrayTree}
|
||||
*/
|
||||
HashedArrayTree.prototype.set = function(index, value) {
|
||||
|
||||
// Out of bounds?
|
||||
if (this.length < index)
|
||||
throw new Error('HashedArrayTree(' + this.ArrayClass.name + ').set: index out of bounds.');
|
||||
|
||||
var block = index >> this.blockMask,
|
||||
i = index & this.offsetMask;
|
||||
|
||||
this.blocks[block][i] = value;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get a value.
|
||||
*
|
||||
* @param {number} index - Index to retrieve.
|
||||
* @return {any}
|
||||
*/
|
||||
HashedArrayTree.prototype.get = function(index) {
|
||||
if (this.length < index)
|
||||
return;
|
||||
|
||||
var block = index >> this.blockMask,
|
||||
i = index & this.offsetMask;
|
||||
|
||||
return this.blocks[block][i];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to grow the array.
|
||||
*
|
||||
* @param {number} capacity - Optional capacity to accomodate.
|
||||
* @return {HashedArrayTree}
|
||||
*/
|
||||
HashedArrayTree.prototype.grow = function(capacity) {
|
||||
if (typeof capacity !== 'number')
|
||||
capacity = this.capacity + this.blockSize;
|
||||
|
||||
if (this.capacity >= capacity)
|
||||
return this;
|
||||
|
||||
while (this.capacity < capacity) {
|
||||
this.blocks.push(new this.ArrayClass(this.blockSize));
|
||||
this.capacity += this.blockSize;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to resize the array. Won't deallocate.
|
||||
*
|
||||
* @param {number} length - Target length.
|
||||
* @return {HashedArrayTree}
|
||||
*/
|
||||
HashedArrayTree.prototype.resize = function(length) {
|
||||
if (length === this.length)
|
||||
return this;
|
||||
|
||||
if (length < this.length) {
|
||||
this.length = length;
|
||||
return this;
|
||||
}
|
||||
|
||||
this.length = length;
|
||||
this.grow(length);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to push a value into the array.
|
||||
*
|
||||
* @param {any} value - Value to push.
|
||||
* @return {number} - Length of the array.
|
||||
*/
|
||||
HashedArrayTree.prototype.push = function(value) {
|
||||
if (this.capacity === this.length)
|
||||
this.grow();
|
||||
|
||||
var index = this.length;
|
||||
|
||||
var block = index >> this.blockMask,
|
||||
i = index & this.offsetMask;
|
||||
|
||||
this.blocks[block][i] = value;
|
||||
|
||||
return ++this.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to pop the last value of the array.
|
||||
*
|
||||
* @return {number} - The popped value.
|
||||
*/
|
||||
HashedArrayTree.prototype.pop = function() {
|
||||
if (this.length === 0)
|
||||
return;
|
||||
|
||||
var lastBlock = this.blocks[this.blocks.length - 1];
|
||||
|
||||
var i = (--this.length) & this.offsetMask;
|
||||
|
||||
return lastBlock[i];
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
HashedArrayTree.prototype.inspect = function() {
|
||||
var proxy = new this.ArrayClass(this.length),
|
||||
block;
|
||||
|
||||
for (var i = 0, l = this.length; i < l; i++) {
|
||||
block = i >> this.blockMask;
|
||||
proxy[i] = this.blocks[block][i & this.offsetMask];
|
||||
}
|
||||
|
||||
proxy.type = this.ArrayClass.name;
|
||||
proxy.items = this.length;
|
||||
proxy.capacity = this.capacity;
|
||||
proxy.blockSize = this.blockSize;
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: HashedArrayTree,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
HashedArrayTree.prototype[Symbol.for('nodejs.util.inspect.custom')] = HashedArrayTree.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = HashedArrayTree;
|
||||
96
backend/node_modules/mnemonist/heap.d.ts
generated
vendored
Normal file
96
backend/node_modules/mnemonist/heap.d.ts
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Mnemonist Heap Typings
|
||||
* =======================
|
||||
*/
|
||||
type HeapComparator<T> = (a: T, b: T) => number;
|
||||
|
||||
export default class Heap<T> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(comparator?: HeapComparator<T>);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
push(item: T): number;
|
||||
peek(): T | undefined;
|
||||
pop(): T | undefined;
|
||||
replace(item: T): T | undefined;
|
||||
pushpop(item: T): T | undefined;
|
||||
toArray(): Array<T>;
|
||||
consume(): Array<T>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(
|
||||
iterable: Iterable<I> | {[key: string]: I},
|
||||
comparator?: HeapComparator<I>
|
||||
): Heap<I>;
|
||||
}
|
||||
|
||||
export class MinHeap<T> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(comparator?: HeapComparator<T>);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
push(item: T): number;
|
||||
peek(): T | undefined;
|
||||
pop(): T | undefined;
|
||||
replace(item: T): T | undefined;
|
||||
pushpop(item: T): T | undefined;
|
||||
toArray(): Array<T>;
|
||||
consume(): Array<T>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(
|
||||
iterable: Iterable<I> | {[key: string]: I},
|
||||
comparator?: HeapComparator<I>
|
||||
): Heap<I>;
|
||||
}
|
||||
|
||||
export class MaxHeap<T> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(comparator?: HeapComparator<T>);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
push(item: T): number;
|
||||
peek(): T | undefined;
|
||||
pop(): T | undefined;
|
||||
replace(item: T): T | undefined;
|
||||
pushpop(item: T): T | undefined;
|
||||
toArray(): Array<T>;
|
||||
consume(): Array<T>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(
|
||||
iterable: Iterable<I> | {[key: string]: I},
|
||||
comparator?: HeapComparator<I>
|
||||
): Heap<I>;
|
||||
}
|
||||
|
||||
// Static helpers
|
||||
export function push<T>(comparator: HeapComparator<T>, heap: Array<T>, item: T): void;
|
||||
export function pop<T>(comparator: HeapComparator<T>, heap: Array<T>): T;
|
||||
export function replace<T>(comparator: HeapComparator<T>, heap: Array<T>, item: T): T;
|
||||
export function pushpop<T>(comparator: HeapComparator<T>, heap: Array<T>, item: T): T;
|
||||
export function heapify<T>(comparator: HeapComparator<T>, array: Array<T>): void;
|
||||
export function consume<T>(comparator: HeapComparator<T>, heap: Array<T>): Array<T>;
|
||||
|
||||
export function nsmallest<T>(comparator: HeapComparator<T>, n: number, values: Iterable<T>): Array<T>;
|
||||
export function nsmallest<T>(n: number, values: Iterable<T>): Array<T>;
|
||||
export function nlargest<T>(comparator: HeapComparator<T>, n: number, values: Iterable<T>): Array<T>;
|
||||
export function nlargest<T>(n: number, values: Iterable<T>): Array<T>;
|
||||
576
backend/node_modules/mnemonist/heap.js
generated
vendored
Normal file
576
backend/node_modules/mnemonist/heap.js
generated
vendored
Normal file
@@ -0,0 +1,576 @@
|
||||
/**
|
||||
* Mnemonist Binary Heap
|
||||
* ======================
|
||||
*
|
||||
* Binary heap implementation.
|
||||
*/
|
||||
var forEach = require('obliterator/foreach'),
|
||||
comparators = require('./utils/comparators.js'),
|
||||
iterables = require('./utils/iterables.js');
|
||||
|
||||
var DEFAULT_COMPARATOR = comparators.DEFAULT_COMPARATOR,
|
||||
reverseComparator = comparators.reverseComparator;
|
||||
|
||||
/**
|
||||
* Heap helper functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Function used to sift down.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @param {number} startIndex - Starting index.
|
||||
* @param {number} i - Index.
|
||||
*/
|
||||
function siftDown(compare, heap, startIndex, i) {
|
||||
var item = heap[i],
|
||||
parentIndex,
|
||||
parent;
|
||||
|
||||
while (i > startIndex) {
|
||||
parentIndex = (i - 1) >> 1;
|
||||
parent = heap[parentIndex];
|
||||
|
||||
if (compare(item, parent) < 0) {
|
||||
heap[i] = parent;
|
||||
i = parentIndex;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
heap[i] = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to sift up.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @param {number} i - Index.
|
||||
*/
|
||||
function siftUp(compare, heap, i) {
|
||||
var endIndex = heap.length,
|
||||
startIndex = i,
|
||||
item = heap[i],
|
||||
childIndex = 2 * i + 1,
|
||||
rightIndex;
|
||||
|
||||
while (childIndex < endIndex) {
|
||||
rightIndex = childIndex + 1;
|
||||
|
||||
if (
|
||||
rightIndex < endIndex &&
|
||||
compare(heap[childIndex], heap[rightIndex]) >= 0
|
||||
) {
|
||||
childIndex = rightIndex;
|
||||
}
|
||||
|
||||
heap[i] = heap[childIndex];
|
||||
i = childIndex;
|
||||
childIndex = 2 * i + 1;
|
||||
}
|
||||
|
||||
heap[i] = item;
|
||||
siftDown(compare, heap, startIndex, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to push an item into a heap represented by a raw array.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @param {any} item - Item to push.
|
||||
*/
|
||||
function push(compare, heap, item) {
|
||||
heap.push(item);
|
||||
siftDown(compare, heap, 0, heap.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to pop an item from a heap represented by a raw array.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @return {any}
|
||||
*/
|
||||
function pop(compare, heap) {
|
||||
var lastItem = heap.pop();
|
||||
|
||||
if (heap.length !== 0) {
|
||||
var item = heap[0];
|
||||
heap[0] = lastItem;
|
||||
siftUp(compare, heap, 0);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
return lastItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to pop the heap then push a new value into it, thus "replacing"
|
||||
* it.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @param {any} item - The item to push.
|
||||
* @return {any}
|
||||
*/
|
||||
function replace(compare, heap, item) {
|
||||
if (heap.length === 0)
|
||||
throw new Error('mnemonist/heap.replace: cannot pop an empty heap.');
|
||||
|
||||
var popped = heap[0];
|
||||
heap[0] = item;
|
||||
siftUp(compare, heap, 0);
|
||||
|
||||
return popped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to push an item in the heap then pop the heap and return the
|
||||
* popped value.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @param {any} item - The item to push.
|
||||
* @return {any}
|
||||
*/
|
||||
function pushpop(compare, heap, item) {
|
||||
var tmp;
|
||||
|
||||
if (heap.length !== 0 && compare(heap[0], item) < 0) {
|
||||
tmp = heap[0];
|
||||
heap[0] = item;
|
||||
item = tmp;
|
||||
siftUp(compare, heap, 0);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts and array into an abstract heap in linear time.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} array - Target array.
|
||||
*/
|
||||
function heapify(compare, array) {
|
||||
var n = array.length,
|
||||
l = n >> 1,
|
||||
i = l;
|
||||
|
||||
while (--i >= 0)
|
||||
siftUp(compare, array, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fully consumes the given heap.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @return {array}
|
||||
*/
|
||||
function consume(compare, heap) {
|
||||
var l = heap.length,
|
||||
i = 0;
|
||||
|
||||
var array = new Array(l);
|
||||
|
||||
while (i < l)
|
||||
array[i++] = pop(compare, heap);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to retrieve the n smallest items from the given iterable.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {number} n - Number of top items to retrieve.
|
||||
* @param {any} iterable - Arbitrary iterable.
|
||||
* @param {array}
|
||||
*/
|
||||
function nsmallest(compare, n, iterable) {
|
||||
if (arguments.length === 2) {
|
||||
iterable = n;
|
||||
n = compare;
|
||||
compare = DEFAULT_COMPARATOR;
|
||||
}
|
||||
|
||||
var reverseCompare = reverseComparator(compare);
|
||||
|
||||
var i, l, v;
|
||||
|
||||
var min = Infinity;
|
||||
|
||||
var result;
|
||||
|
||||
// If n is equal to 1, it's just a matter of finding the minimum
|
||||
if (n === 1) {
|
||||
if (iterables.isArrayLike(iterable)) {
|
||||
for (i = 0, l = iterable.length; i < l; i++) {
|
||||
v = iterable[i];
|
||||
|
||||
if (min === Infinity || compare(v, min) < 0)
|
||||
min = v;
|
||||
}
|
||||
|
||||
result = new iterable.constructor(1);
|
||||
result[0] = min;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
if (min === Infinity || compare(value, min) < 0)
|
||||
min = value;
|
||||
});
|
||||
|
||||
return [min];
|
||||
}
|
||||
|
||||
if (iterables.isArrayLike(iterable)) {
|
||||
|
||||
// If n > iterable length, we just clone and sort
|
||||
if (n >= iterable.length)
|
||||
return iterable.slice().sort(compare);
|
||||
|
||||
result = iterable.slice(0, n);
|
||||
heapify(reverseCompare, result);
|
||||
|
||||
for (i = n, l = iterable.length; i < l; i++)
|
||||
if (reverseCompare(iterable[i], result[0]) > 0)
|
||||
replace(reverseCompare, result, iterable[i]);
|
||||
|
||||
// NOTE: if n is over some number, it becomes faster to consume the heap
|
||||
return result.sort(compare);
|
||||
}
|
||||
|
||||
// Correct for size
|
||||
var size = iterables.guessLength(iterable);
|
||||
|
||||
if (size !== null && size < n)
|
||||
n = size;
|
||||
|
||||
result = new Array(n);
|
||||
i = 0;
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
if (i < n) {
|
||||
result[i] = value;
|
||||
}
|
||||
else {
|
||||
if (i === n)
|
||||
heapify(reverseCompare, result);
|
||||
|
||||
if (reverseCompare(value, result[0]) > 0)
|
||||
replace(reverseCompare, result, value);
|
||||
}
|
||||
|
||||
i++;
|
||||
});
|
||||
|
||||
if (result.length > i)
|
||||
result.length = i;
|
||||
|
||||
// NOTE: if n is over some number, it becomes faster to consume the heap
|
||||
return result.sort(compare);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to retrieve the n largest items from the given iterable.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {number} n - Number of top items to retrieve.
|
||||
* @param {any} iterable - Arbitrary iterable.
|
||||
* @param {array}
|
||||
*/
|
||||
function nlargest(compare, n, iterable) {
|
||||
if (arguments.length === 2) {
|
||||
iterable = n;
|
||||
n = compare;
|
||||
compare = DEFAULT_COMPARATOR;
|
||||
}
|
||||
|
||||
var reverseCompare = reverseComparator(compare);
|
||||
|
||||
var i, l, v;
|
||||
|
||||
var max = -Infinity;
|
||||
|
||||
var result;
|
||||
|
||||
// If n is equal to 1, it's just a matter of finding the maximum
|
||||
if (n === 1) {
|
||||
if (iterables.isArrayLike(iterable)) {
|
||||
for (i = 0, l = iterable.length; i < l; i++) {
|
||||
v = iterable[i];
|
||||
|
||||
if (max === -Infinity || compare(v, max) > 0)
|
||||
max = v;
|
||||
}
|
||||
|
||||
result = new iterable.constructor(1);
|
||||
result[0] = max;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
if (max === -Infinity || compare(value, max) > 0)
|
||||
max = value;
|
||||
});
|
||||
|
||||
return [max];
|
||||
}
|
||||
|
||||
if (iterables.isArrayLike(iterable)) {
|
||||
|
||||
// If n > iterable length, we just clone and sort
|
||||
if (n >= iterable.length)
|
||||
return iterable.slice().sort(reverseCompare);
|
||||
|
||||
result = iterable.slice(0, n);
|
||||
heapify(compare, result);
|
||||
|
||||
for (i = n, l = iterable.length; i < l; i++)
|
||||
if (compare(iterable[i], result[0]) > 0)
|
||||
replace(compare, result, iterable[i]);
|
||||
|
||||
// NOTE: if n is over some number, it becomes faster to consume the heap
|
||||
return result.sort(reverseCompare);
|
||||
}
|
||||
|
||||
// Correct for size
|
||||
var size = iterables.guessLength(iterable);
|
||||
|
||||
if (size !== null && size < n)
|
||||
n = size;
|
||||
|
||||
result = new Array(n);
|
||||
i = 0;
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
if (i < n) {
|
||||
result[i] = value;
|
||||
}
|
||||
else {
|
||||
if (i === n)
|
||||
heapify(compare, result);
|
||||
|
||||
if (compare(value, result[0]) > 0)
|
||||
replace(compare, result, value);
|
||||
}
|
||||
|
||||
i++;
|
||||
});
|
||||
|
||||
if (result.length > i)
|
||||
result.length = i;
|
||||
|
||||
// NOTE: if n is over some number, it becomes faster to consume the heap
|
||||
return result.sort(reverseCompare);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binary Minimum Heap.
|
||||
*
|
||||
* @constructor
|
||||
* @param {function} comparator - Comparator function to use.
|
||||
*/
|
||||
function Heap(comparator) {
|
||||
this.clear();
|
||||
this.comparator = comparator || DEFAULT_COMPARATOR;
|
||||
|
||||
if (typeof this.comparator !== 'function')
|
||||
throw new Error('mnemonist/Heap.constructor: given comparator should be a function.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the heap.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
Heap.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.items = [];
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to push an item into the heap.
|
||||
*
|
||||
* @param {any} item - Item to push.
|
||||
* @return {number}
|
||||
*/
|
||||
Heap.prototype.push = function(item) {
|
||||
push(this.comparator, this.items, item);
|
||||
return ++this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to retrieve the "first" item of the heap.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
Heap.prototype.peek = function() {
|
||||
return this.items[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to retrieve & remove the "first" item of the heap.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
Heap.prototype.pop = function() {
|
||||
if (this.size !== 0)
|
||||
this.size--;
|
||||
|
||||
return pop(this.comparator, this.items);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to pop the heap, then push an item and return the popped
|
||||
* item.
|
||||
*
|
||||
* @param {any} item - Item to push into the heap.
|
||||
* @return {any}
|
||||
*/
|
||||
Heap.prototype.replace = function(item) {
|
||||
return replace(this.comparator, this.items, item);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to push the heap, the pop it and return the pooped item.
|
||||
*
|
||||
* @param {any} item - Item to push into the heap.
|
||||
* @return {any}
|
||||
*/
|
||||
Heap.prototype.pushpop = function(item) {
|
||||
return pushpop(this.comparator, this.items, item);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to consume the heap fully and return its items as a sorted array.
|
||||
*
|
||||
* @return {array}
|
||||
*/
|
||||
Heap.prototype.consume = function() {
|
||||
this.size = 0;
|
||||
return consume(this.comparator, this.items);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to convert the heap to an array. Note that it basically clone
|
||||
* the heap and consumes it completely. This is hardly performant.
|
||||
*
|
||||
* @return {array}
|
||||
*/
|
||||
Heap.prototype.toArray = function() {
|
||||
return consume(this.comparator, this.items.slice());
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
Heap.prototype.inspect = function() {
|
||||
var proxy = this.toArray();
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: Heap,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
Heap.prototype[Symbol.for('nodejs.util.inspect.custom')] = Heap.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Binary Maximum Heap.
|
||||
*
|
||||
* @constructor
|
||||
* @param {function} comparator - Comparator function to use.
|
||||
*/
|
||||
function MaxHeap(comparator) {
|
||||
this.clear();
|
||||
this.comparator = comparator || DEFAULT_COMPARATOR;
|
||||
|
||||
if (typeof this.comparator !== 'function')
|
||||
throw new Error('mnemonist/MaxHeap.constructor: given comparator should be a function.');
|
||||
|
||||
this.comparator = reverseComparator(this.comparator);
|
||||
}
|
||||
|
||||
MaxHeap.prototype = Heap.prototype;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a heap.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {function} comparator - Custom comparator function.
|
||||
* @return {Heap}
|
||||
*/
|
||||
Heap.from = function(iterable, comparator) {
|
||||
var heap = new Heap(comparator);
|
||||
|
||||
var items;
|
||||
|
||||
// If iterable is an array, we can be clever about it
|
||||
if (iterables.isArrayLike(iterable))
|
||||
items = iterable.slice();
|
||||
else
|
||||
items = iterables.toArray(iterable);
|
||||
|
||||
heapify(heap.comparator, items);
|
||||
heap.items = items;
|
||||
heap.size = items.length;
|
||||
|
||||
return heap;
|
||||
};
|
||||
|
||||
MaxHeap.from = function(iterable, comparator) {
|
||||
var heap = new MaxHeap(comparator);
|
||||
|
||||
var items;
|
||||
|
||||
// If iterable is an array, we can be clever about it
|
||||
if (iterables.isArrayLike(iterable))
|
||||
items = iterable.slice();
|
||||
else
|
||||
items = iterables.toArray(iterable);
|
||||
|
||||
heapify(heap.comparator, items);
|
||||
heap.items = items;
|
||||
heap.size = items.length;
|
||||
|
||||
return heap;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
Heap.siftUp = siftUp;
|
||||
Heap.siftDown = siftDown;
|
||||
Heap.push = push;
|
||||
Heap.pop = pop;
|
||||
Heap.replace = replace;
|
||||
Heap.pushpop = pushpop;
|
||||
Heap.heapify = heapify;
|
||||
Heap.consume = consume;
|
||||
|
||||
Heap.nsmallest = nsmallest;
|
||||
Heap.nlargest = nlargest;
|
||||
|
||||
Heap.MinHeap = Heap;
|
||||
Heap.MaxHeap = MaxHeap;
|
||||
|
||||
module.exports = Heap;
|
||||
48
backend/node_modules/mnemonist/index.d.ts
generated
vendored
Normal file
48
backend/node_modules/mnemonist/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Mnemonist Typings
|
||||
* ==================
|
||||
*
|
||||
* Gathering the library's typings.
|
||||
*/
|
||||
import * as set from './set';
|
||||
|
||||
export {default as BiMap, InverseMap} from './bi-map';
|
||||
export {default as BitSet} from './bit-set';
|
||||
export {default as BitVector} from './bit-vector';
|
||||
export {default as BKTree} from './bk-tree';
|
||||
export {default as BloomFilter} from './bloom-filter';
|
||||
export {default as CircularBuffer} from './circular-buffer';
|
||||
export {default as DefaultMap} from './default-map';
|
||||
export {default as DefaultWeakMap} from './default-weak-map';
|
||||
export {default as FixedDeque} from './fixed-deque';
|
||||
export {default as FibonacciHeap, MinFibonacciHeap, MaxFibonacciHeap} from './fibonacci-heap';
|
||||
export {default as FixedReverseHeap} from './fixed-reverse-heap';
|
||||
export {default as FixedStack} from './fixed-stack';
|
||||
export {default as FuzzyMap} from './fuzzy-map';
|
||||
export {default as FuzzyMultiMap} from './fuzzy-multi-map';
|
||||
export {default as HashedArrayTree} from './hashed-array-tree';
|
||||
export {default as Heap, MinHeap, MaxHeap} from './heap';
|
||||
export {default as InvertedIndex} from './inverted-index';
|
||||
export {default as KDTree} from './kd-tree';
|
||||
export {default as LinkedList} from './linked-list';
|
||||
export {default as LRUCache} from './lru-cache';
|
||||
export {default as LRUCacheWithDelete} from './lru-cache-with-delete';
|
||||
export {default as LRUMap} from './lru-map';
|
||||
export {default as LRUMapWithDelete} from './lru-map-with-delete';
|
||||
export {default as MultiMap} from './multi-map';
|
||||
export {default as MultiSet} from './multi-set';
|
||||
export {default as PassjoinIndex} from './passjoin-index';
|
||||
export {default as Queue} from './queue';
|
||||
export {set};
|
||||
export {default as SparseQueueSet} from './sparse-queue-set';
|
||||
export {default as SparseMap} from './sparse-map';
|
||||
export {default as SparseSet} from './sparse-set';
|
||||
export {default as Stack} from './stack';
|
||||
export {default as StaticDisjointSet} from './static-disjoint-set';
|
||||
export {default as StaticIntervalTree} from './static-interval-tree';
|
||||
export {default as SuffixArray, GeneralizedSuffixArray} from './suffix-array';
|
||||
export {default as SymSpell} from './symspell';
|
||||
export {default as Trie} from './trie';
|
||||
export {default as TrieMap} from './trie-map';
|
||||
export {default as Vector, Uint8Vector, Uint8ClampedVector, Int8Vector, Uint16Vector, Int16Vector, Uint32Vector, Int32Vector, Float32Vector, Float64Array} from './vector';
|
||||
export {default as VPTree} from './vp-tree';
|
||||
58
backend/node_modules/mnemonist/index.js
generated
vendored
Normal file
58
backend/node_modules/mnemonist/index.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Mnemonist Library Endpoint
|
||||
* ===========================
|
||||
*
|
||||
* Exporting every data structure through a unified endpoint. Consumers
|
||||
* of this library should prefer the modular access though.
|
||||
*/
|
||||
var Heap = require('./heap.js'),
|
||||
FibonacciHeap = require('./fibonacci-heap.js'),
|
||||
SuffixArray = require('./suffix-array.js');
|
||||
|
||||
module.exports = {
|
||||
BiMap: require('./bi-map.js'),
|
||||
BitSet: require('./bit-set.js'),
|
||||
BitVector: require('./bit-vector.js'),
|
||||
BloomFilter: require('./bloom-filter.js'),
|
||||
BKTree: require('./bk-tree.js'),
|
||||
CircularBuffer: require('./circular-buffer.js'),
|
||||
DefaultMap: require('./default-map.js'),
|
||||
DefaultWeakMap: require('./default-weak-map.js'),
|
||||
FixedDeque: require('./fixed-deque.js'),
|
||||
StaticDisjointSet: require('./static-disjoint-set.js'),
|
||||
FibonacciHeap: FibonacciHeap,
|
||||
MinFibonacciHeap: FibonacciHeap.MinFibonacciHeap,
|
||||
MaxFibonacciHeap: FibonacciHeap.MaxFibonacciHeap,
|
||||
FixedReverseHeap: require('./fixed-reverse-heap.js'),
|
||||
FuzzyMap: require('./fuzzy-map.js'),
|
||||
FuzzyMultiMap: require('./fuzzy-multi-map.js'),
|
||||
HashedArrayTree: require('./hashed-array-tree.js'),
|
||||
Heap: Heap,
|
||||
MinHeap: Heap.MinHeap,
|
||||
MaxHeap: Heap.MaxHeap,
|
||||
StaticIntervalTree: require('./static-interval-tree.js'),
|
||||
InvertedIndex: require('./inverted-index.js'),
|
||||
KDTree: require('./kd-tree.js'),
|
||||
LinkedList: require('./linked-list.js'),
|
||||
LRUCache: require('./lru-cache.js'),
|
||||
LRUCacheWithDelete: require('./lru-cache-with-delete.js'),
|
||||
LRUMap: require('./lru-map.js'),
|
||||
LRUMapWithDelete: require('./lru-map-with-delete.js'),
|
||||
MultiMap: require('./multi-map.js'),
|
||||
MultiSet: require('./multi-set.js'),
|
||||
PassjoinIndex: require('./passjoin-index.js'),
|
||||
Queue: require('./queue.js'),
|
||||
FixedStack: require('./fixed-stack.js'),
|
||||
Stack: require('./stack.js'),
|
||||
SuffixArray: SuffixArray,
|
||||
GeneralizedSuffixArray: SuffixArray.GeneralizedSuffixArray,
|
||||
Set: require('./set.js'),
|
||||
SparseQueueSet: require('./sparse-queue-set.js'),
|
||||
SparseMap: require('./sparse-map.js'),
|
||||
SparseSet: require('./sparse-set.js'),
|
||||
SymSpell: require('./symspell.js'),
|
||||
Trie: require('./trie.js'),
|
||||
TrieMap: require('./trie-map.js'),
|
||||
Vector: require('./vector.js'),
|
||||
VPTree: require('./vp-tree.js')
|
||||
};
|
||||
33
backend/node_modules/mnemonist/inverted-index.d.ts
generated
vendored
Normal file
33
backend/node_modules/mnemonist/inverted-index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Mnemonist InvertedIndex Typings
|
||||
* ================================
|
||||
*/
|
||||
type Tokenizer = (key: any) => Array<string>;
|
||||
type TokenizersTuple = [Tokenizer, Tokenizer];
|
||||
|
||||
export default class InvertedIndex<D> implements Iterable<D> {
|
||||
|
||||
// Members
|
||||
dimension: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(tokenizer?: Tokenizer);
|
||||
constructor(tokenizers?: TokenizersTuple);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
add(document: D): this;
|
||||
get(query: any): Array<D>;
|
||||
forEach(callback: (document: D, index: number, invertedIndex: this) => void, scope?: any): void;
|
||||
documents(): IterableIterator<D>;
|
||||
tokens(): IterableIterator<string>;
|
||||
[Symbol.iterator](): IterableIterator<D>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(
|
||||
iterable: Iterable<I> | {[key: string]: I},
|
||||
tokenizer?: Tokenizer | TokenizersTuple
|
||||
): InvertedIndex<I>;
|
||||
}
|
||||
249
backend/node_modules/mnemonist/inverted-index.js
generated
vendored
Normal file
249
backend/node_modules/mnemonist/inverted-index.js
generated
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* Mnemonist Inverted Index
|
||||
* =========================
|
||||
*
|
||||
* JavaScript implementation of an inverted index.
|
||||
*/
|
||||
var Iterator = require('obliterator/iterator'),
|
||||
forEach = require('obliterator/foreach'),
|
||||
helpers = require('./utils/merge.js');
|
||||
|
||||
function identity(x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* InvertedIndex.
|
||||
*
|
||||
* @constructor
|
||||
* @param {function} tokenizer - Tokenizer function.
|
||||
*/
|
||||
function InvertedIndex(descriptor) {
|
||||
this.clear();
|
||||
|
||||
if (Array.isArray(descriptor)) {
|
||||
this.documentTokenizer = descriptor[0];
|
||||
this.queryTokenizer = descriptor[1];
|
||||
}
|
||||
else {
|
||||
this.documentTokenizer = descriptor;
|
||||
this.queryTokenizer = descriptor;
|
||||
}
|
||||
|
||||
if (!this.documentTokenizer)
|
||||
this.documentTokenizer = identity;
|
||||
if (!this.queryTokenizer)
|
||||
this.queryTokenizer = identity;
|
||||
|
||||
if (typeof this.documentTokenizer !== 'function')
|
||||
throw new Error('mnemonist/InvertedIndex.constructor: document tokenizer is not a function.');
|
||||
|
||||
if (typeof this.queryTokenizer !== 'function')
|
||||
throw new Error('mnemonist/InvertedIndex.constructor: query tokenizer is not a function.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the InvertedIndex.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
InvertedIndex.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.items = [];
|
||||
this.mapping = new Map();
|
||||
this.size = 0;
|
||||
this.dimension = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add a document to the index.
|
||||
*
|
||||
* @param {any} doc - Item to add.
|
||||
* @return {InvertedIndex}
|
||||
*/
|
||||
InvertedIndex.prototype.add = function(doc) {
|
||||
|
||||
// Increasing size
|
||||
this.size++;
|
||||
|
||||
// Storing document
|
||||
var key = this.items.length;
|
||||
this.items.push(doc);
|
||||
|
||||
// Tokenizing the document
|
||||
var tokens = this.documentTokenizer(doc);
|
||||
|
||||
if (!Array.isArray(tokens))
|
||||
throw new Error('mnemonist/InvertedIndex.add: tokenizer function should return an array of tokens.');
|
||||
|
||||
// Indexing
|
||||
var done = new Set(),
|
||||
token,
|
||||
container;
|
||||
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
token = tokens[i];
|
||||
|
||||
if (done.has(token))
|
||||
continue;
|
||||
|
||||
done.add(token);
|
||||
|
||||
container = this.mapping.get(token);
|
||||
|
||||
if (!container) {
|
||||
container = [];
|
||||
this.mapping.set(token, container);
|
||||
}
|
||||
|
||||
container.push(key);
|
||||
}
|
||||
|
||||
this.dimension = this.mapping.size;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to query the index in a AND fashion.
|
||||
*
|
||||
* @param {any} query - Query
|
||||
* @return {Set} - Intersection of documents matching the query.
|
||||
*/
|
||||
InvertedIndex.prototype.get = function(query) {
|
||||
|
||||
// Early termination
|
||||
if (!this.size)
|
||||
return [];
|
||||
|
||||
// First we need to tokenize the query
|
||||
var tokens = this.queryTokenizer(query);
|
||||
|
||||
if (!Array.isArray(tokens))
|
||||
throw new Error('mnemonist/InvertedIndex.query: tokenizer function should return an array of tokens.');
|
||||
|
||||
if (!tokens.length)
|
||||
return [];
|
||||
|
||||
var results = this.mapping.get(tokens[0]),
|
||||
c,
|
||||
i,
|
||||
l;
|
||||
|
||||
if (typeof results === 'undefined' || results.length === 0)
|
||||
return [];
|
||||
|
||||
if (tokens.length > 1) {
|
||||
for (i = 1, l = tokens.length; i < l; i++) {
|
||||
c = this.mapping.get(tokens[i]);
|
||||
|
||||
if (typeof c === 'undefined' || c.length === 0)
|
||||
return [];
|
||||
|
||||
results = helpers.intersectionUniqueArrays(results, c);
|
||||
}
|
||||
}
|
||||
|
||||
var docs = new Array(results.length);
|
||||
|
||||
for (i = 0, l = docs.length; i < l; i++)
|
||||
docs[i] = this.items[results[i]];
|
||||
|
||||
return docs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over each of the documents.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
InvertedIndex.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
for (var i = 0, l = this.documents.length; i < l; i++)
|
||||
callback.call(scope, this.documents[i], i, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the index's documents.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
InvertedIndex.prototype.documents = function() {
|
||||
var documents = this.items,
|
||||
l = documents.length,
|
||||
i = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= l)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
var value = documents[i++];
|
||||
|
||||
return {
|
||||
value: value,
|
||||
done: false
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the index's tokens.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
InvertedIndex.prototype.tokens = function() {
|
||||
return this.mapping.keys();
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.values method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
InvertedIndex.prototype[Symbol.iterator] = InvertedIndex.prototype.documents;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
InvertedIndex.prototype.inspect = function() {
|
||||
var array = this.items.slice();
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(array, 'constructor', {
|
||||
value: InvertedIndex,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
InvertedIndex.prototype[Symbol.for('nodejs.util.inspect.custom')] = InvertedIndex.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a InvertedIndex.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {function} tokenizer - Tokenizer function.
|
||||
* @return {InvertedIndex}
|
||||
*/
|
||||
InvertedIndex.from = function(iterable, descriptor) {
|
||||
var index = new InvertedIndex(descriptor);
|
||||
|
||||
forEach(iterable, function(doc) {
|
||||
index.add(doc);
|
||||
});
|
||||
|
||||
return index;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = InvertedIndex;
|
||||
25
backend/node_modules/mnemonist/kd-tree.d.ts
generated
vendored
Normal file
25
backend/node_modules/mnemonist/kd-tree.d.ts
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Mnemonist KDTree Typings
|
||||
* =========================
|
||||
*/
|
||||
import {IArrayLike} from './utils/types';
|
||||
|
||||
export default class KDTree<V> {
|
||||
|
||||
// Members
|
||||
dimensions: number;
|
||||
size: number;
|
||||
visited: number;
|
||||
|
||||
// Methods
|
||||
nearestNeighbor(point: Array<number>): V;
|
||||
kNearestNeighbors(k: number, point: Array<number>): Array<V>;
|
||||
linearKNearestNeighbors(k: number, point: Array<number>): Array<V>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(iterable: Iterable<[I, Array<number>]>, dimensions: number): KDTree<I>;
|
||||
static fromAxes(axes: IArrayLike): KDTree<number>;
|
||||
static fromAxes<I>(axes: IArrayLike, labels: Array<I>): KDTree<I>;
|
||||
}
|
||||
|
||||
447
backend/node_modules/mnemonist/kd-tree.js
generated
vendored
Normal file
447
backend/node_modules/mnemonist/kd-tree.js
generated
vendored
Normal file
@@ -0,0 +1,447 @@
|
||||
/**
|
||||
* Mnemonist KDTree
|
||||
* =================
|
||||
*
|
||||
* Low-level JavaScript implementation of a k-dimensional tree.
|
||||
*/
|
||||
var iterables = require('./utils/iterables.js');
|
||||
var typed = require('./utils/typed-arrays.js');
|
||||
var createTupleComparator = require('./utils/comparators.js').createTupleComparator;
|
||||
var FixedReverseHeap = require('./fixed-reverse-heap.js');
|
||||
var inplaceQuickSortIndices = require('./sort/quick.js').inplaceQuickSortIndices;
|
||||
|
||||
/**
|
||||
* Helper function used to compute the squared distance between a query point
|
||||
* and an indexed points whose values are stored in a tree's axes.
|
||||
*
|
||||
* Note that squared distance is used instead of euclidean to avoid
|
||||
* costly sqrt computations.
|
||||
*
|
||||
* @param {number} dimensions - Number of dimensions.
|
||||
* @param {array} axes - Axes data.
|
||||
* @param {number} pivot - Pivot.
|
||||
* @param {array} point - Query point.
|
||||
* @return {number}
|
||||
*/
|
||||
function squaredDistanceAxes(dimensions, axes, pivot, b) {
|
||||
var d;
|
||||
|
||||
var dist = 0,
|
||||
step;
|
||||
|
||||
for (d = 0; d < dimensions; d++) {
|
||||
step = axes[d][pivot] - b[d];
|
||||
dist += step * step;
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function used to reshape input data into low-level axes data.
|
||||
*
|
||||
* @param {number} dimensions - Number of dimensions.
|
||||
* @param {array} data - Data in the shape [label, [x, y, z...]]
|
||||
* @return {object}
|
||||
*/
|
||||
function reshapeIntoAxes(dimensions, data) {
|
||||
var l = data.length;
|
||||
|
||||
var axes = new Array(dimensions),
|
||||
labels = new Array(l),
|
||||
axis;
|
||||
|
||||
var PointerArray = typed.getPointerArray(l);
|
||||
|
||||
var ids = new PointerArray(l);
|
||||
|
||||
var d, i, row;
|
||||
|
||||
var f = true;
|
||||
|
||||
for (d = 0; d < dimensions; d++) {
|
||||
axis = new Float64Array(l);
|
||||
|
||||
for (i = 0; i < l; i++) {
|
||||
row = data[i];
|
||||
axis[i] = row[1][d];
|
||||
|
||||
if (f) {
|
||||
labels[i] = row[0];
|
||||
ids[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
f = false;
|
||||
axes[d] = axis;
|
||||
}
|
||||
|
||||
return {axes: axes, ids: ids, labels: labels};
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function used to build a kd-tree from axes data.
|
||||
*
|
||||
* @param {number} dimensions - Number of dimensions.
|
||||
* @param {array} axes - Axes.
|
||||
* @param {array} ids - Indices to sort.
|
||||
* @param {array} labels - Point labels.
|
||||
* @return {object}
|
||||
*/
|
||||
function buildTree(dimensions, axes, ids, labels) {
|
||||
var l = labels.length;
|
||||
|
||||
// NOTE: +1 because we need to keep 0 as null pointer
|
||||
var PointerArray = typed.getPointerArray(l + 1);
|
||||
|
||||
// Building the tree
|
||||
var pivots = new PointerArray(l),
|
||||
lefts = new PointerArray(l),
|
||||
rights = new PointerArray(l);
|
||||
|
||||
var stack = [[0, 0, ids.length, -1, 0]],
|
||||
step,
|
||||
parent,
|
||||
direction,
|
||||
median,
|
||||
pivot,
|
||||
lo,
|
||||
hi;
|
||||
|
||||
var d, i = 0;
|
||||
|
||||
while (stack.length !== 0) {
|
||||
step = stack.pop();
|
||||
|
||||
d = step[0];
|
||||
lo = step[1];
|
||||
hi = step[2];
|
||||
parent = step[3];
|
||||
direction = step[4];
|
||||
|
||||
inplaceQuickSortIndices(axes[d], ids, lo, hi);
|
||||
|
||||
l = hi - lo;
|
||||
median = lo + (l >>> 1); // Fancy floor(l / 2)
|
||||
pivot = ids[median];
|
||||
pivots[i] = pivot;
|
||||
|
||||
if (parent > -1) {
|
||||
if (direction === 0)
|
||||
lefts[parent] = i + 1;
|
||||
else
|
||||
rights[parent] = i + 1;
|
||||
}
|
||||
|
||||
d = (d + 1) % dimensions;
|
||||
|
||||
// Right
|
||||
if (median !== lo && median !== hi - 1) {
|
||||
stack.push([d, median + 1, hi, i, 1]);
|
||||
}
|
||||
|
||||
// Left
|
||||
if (median !== lo) {
|
||||
stack.push([d, lo, median, i, 0]);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return {
|
||||
axes: axes,
|
||||
labels: labels,
|
||||
pivots: pivots,
|
||||
lefts: lefts,
|
||||
rights: rights
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* KDTree.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function KDTree(dimensions, build) {
|
||||
this.dimensions = dimensions;
|
||||
this.visited = 0;
|
||||
|
||||
this.axes = build.axes;
|
||||
this.labels = build.labels;
|
||||
|
||||
this.pivots = build.pivots;
|
||||
this.lefts = build.lefts;
|
||||
this.rights = build.rights;
|
||||
|
||||
this.size = this.labels.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method returning the query's nearest neighbor.
|
||||
*
|
||||
* @param {array} query - Query point.
|
||||
* @return {any}
|
||||
*/
|
||||
KDTree.prototype.nearestNeighbor = function(query) {
|
||||
var bestDistance = Infinity,
|
||||
best = null;
|
||||
|
||||
var dimensions = this.dimensions,
|
||||
axes = this.axes,
|
||||
pivots = this.pivots,
|
||||
lefts = this.lefts,
|
||||
rights = this.rights;
|
||||
|
||||
var visited = 0;
|
||||
|
||||
function recurse(d, node) {
|
||||
visited++;
|
||||
|
||||
var left = lefts[node],
|
||||
right = rights[node],
|
||||
pivot = pivots[node];
|
||||
|
||||
var dist = squaredDistanceAxes(
|
||||
dimensions,
|
||||
axes,
|
||||
pivot,
|
||||
query
|
||||
);
|
||||
|
||||
if (dist < bestDistance) {
|
||||
best = pivot;
|
||||
bestDistance = dist;
|
||||
|
||||
if (dist === 0)
|
||||
return;
|
||||
}
|
||||
|
||||
var dx = axes[d][pivot] - query[d];
|
||||
|
||||
d = (d + 1) % dimensions;
|
||||
|
||||
// Going the correct way?
|
||||
if (dx > 0) {
|
||||
if (left !== 0)
|
||||
recurse(d, left - 1);
|
||||
}
|
||||
else {
|
||||
if (right !== 0)
|
||||
recurse(d, right - 1);
|
||||
}
|
||||
|
||||
// Going the other way?
|
||||
if (dx * dx < bestDistance) {
|
||||
if (dx > 0) {
|
||||
if (right !== 0)
|
||||
recurse(d, right - 1);
|
||||
}
|
||||
else {
|
||||
if (left !== 0)
|
||||
recurse(d, left - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recurse(0, 0);
|
||||
|
||||
this.visited = visited;
|
||||
return this.labels[best];
|
||||
};
|
||||
|
||||
var KNN_HEAP_COMPARATOR_3 = createTupleComparator(3);
|
||||
var KNN_HEAP_COMPARATOR_2 = createTupleComparator(2);
|
||||
|
||||
/**
|
||||
* Method returning the query's k nearest neighbors.
|
||||
*
|
||||
* @param {number} k - Number of nearest neighbor to retrieve.
|
||||
* @param {array} query - Query point.
|
||||
* @return {array}
|
||||
*/
|
||||
|
||||
// TODO: can do better by improving upon static-kdtree here
|
||||
KDTree.prototype.kNearestNeighbors = function(k, query) {
|
||||
if (k <= 0)
|
||||
throw new Error('mnemonist/kd-tree.kNearestNeighbors: k should be a positive number.');
|
||||
|
||||
k = Math.min(k, this.size);
|
||||
|
||||
if (k === 1)
|
||||
return [this.nearestNeighbor(query)];
|
||||
|
||||
var heap = new FixedReverseHeap(Array, KNN_HEAP_COMPARATOR_3, k);
|
||||
|
||||
var dimensions = this.dimensions,
|
||||
axes = this.axes,
|
||||
pivots = this.pivots,
|
||||
lefts = this.lefts,
|
||||
rights = this.rights;
|
||||
|
||||
var visited = 0;
|
||||
|
||||
function recurse(d, node) {
|
||||
var left = lefts[node],
|
||||
right = rights[node],
|
||||
pivot = pivots[node];
|
||||
|
||||
var dist = squaredDistanceAxes(
|
||||
dimensions,
|
||||
axes,
|
||||
pivot,
|
||||
query
|
||||
);
|
||||
|
||||
heap.push([dist, visited++, pivot]);
|
||||
|
||||
var point = query[d],
|
||||
split = axes[d][pivot],
|
||||
dx = point - split;
|
||||
|
||||
d = (d + 1) % dimensions;
|
||||
|
||||
// Going the correct way?
|
||||
if (point < split) {
|
||||
if (left !== 0) {
|
||||
recurse(d, left - 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (right !== 0) {
|
||||
recurse(d, right - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Going the other way?
|
||||
if (dx * dx < heap.peek()[0] || heap.size < k) {
|
||||
if (point < split) {
|
||||
if (right !== 0) {
|
||||
recurse(d, right - 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (left !== 0) {
|
||||
recurse(d, left - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recurse(0, 0);
|
||||
|
||||
this.visited = visited;
|
||||
|
||||
var best = heap.consume();
|
||||
|
||||
for (var i = 0; i < best.length; i++)
|
||||
best[i] = this.labels[best[i][2]];
|
||||
|
||||
return best;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning the query's k nearest neighbors by linear search.
|
||||
*
|
||||
* @param {number} k - Number of nearest neighbor to retrieve.
|
||||
* @param {array} query - Query point.
|
||||
* @return {array}
|
||||
*/
|
||||
KDTree.prototype.linearKNearestNeighbors = function(k, query) {
|
||||
if (k <= 0)
|
||||
throw new Error('mnemonist/kd-tree.kNearestNeighbors: k should be a positive number.');
|
||||
|
||||
k = Math.min(k, this.size);
|
||||
|
||||
var heap = new FixedReverseHeap(Array, KNN_HEAP_COMPARATOR_2, k);
|
||||
|
||||
var i, l, dist;
|
||||
|
||||
for (i = 0, l = this.size; i < l; i++) {
|
||||
dist = squaredDistanceAxes(
|
||||
this.dimensions,
|
||||
this.axes,
|
||||
this.pivots[i],
|
||||
query
|
||||
);
|
||||
|
||||
heap.push([dist, i]);
|
||||
}
|
||||
|
||||
var best = heap.consume();
|
||||
|
||||
for (i = 0; i < best.length; i++)
|
||||
best[i] = this.labels[this.pivots[best[i][1]]];
|
||||
|
||||
return best;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
KDTree.prototype.inspect = function() {
|
||||
var dummy = new Map();
|
||||
|
||||
dummy.dimensions = this.dimensions;
|
||||
|
||||
Object.defineProperty(dummy, 'constructor', {
|
||||
value: KDTree,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
var i, j, point;
|
||||
|
||||
for (i = 0; i < this.size; i++) {
|
||||
point = new Array(this.dimensions);
|
||||
|
||||
for (j = 0; j < this.dimensions; j++)
|
||||
point[j] = this.axes[j][i];
|
||||
|
||||
dummy.set(this.labels[i], point);
|
||||
}
|
||||
|
||||
return dummy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
KDTree.prototype[Symbol.for('nodejs.util.inspect.custom')] = KDTree.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a structure.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {number} dimensions - Space dimensions.
|
||||
* @return {KDTree}
|
||||
*/
|
||||
KDTree.from = function(iterable, dimensions) {
|
||||
var data = iterables.toArray(iterable);
|
||||
|
||||
var reshaped = reshapeIntoAxes(dimensions, data);
|
||||
|
||||
var result = buildTree(dimensions, reshaped.axes, reshaped.ids, reshaped.labels);
|
||||
|
||||
return new KDTree(dimensions, result);
|
||||
};
|
||||
|
||||
/**
|
||||
* Static @.from function building a KDTree from given axes.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {number} dimensions - Space dimensions.
|
||||
* @return {KDTree}
|
||||
*/
|
||||
KDTree.fromAxes = function(axes, labels) {
|
||||
if (!labels)
|
||||
labels = typed.indices(axes[0].length);
|
||||
|
||||
var dimensions = axes.length;
|
||||
|
||||
var result = buildTree(axes.length, axes, typed.indices(labels.length), labels);
|
||||
|
||||
return new KDTree(dimensions, result);
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = KDTree;
|
||||
29
backend/node_modules/mnemonist/linked-list.d.ts
generated
vendored
Normal file
29
backend/node_modules/mnemonist/linked-list.d.ts
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Mnemonist LinkedList Typings
|
||||
* =============================
|
||||
*/
|
||||
export default class LinkedList<T> implements Iterable<T> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
first(): T | undefined;
|
||||
last(): T | undefined;
|
||||
peek(): T | undefined;
|
||||
push(value: T): number;
|
||||
shift(): T | undefined;
|
||||
unshift(value: T): number;
|
||||
forEach(callback: (value: T, index: number, list: this) => void, scope?: any): void;
|
||||
toArray(): Array<T>;
|
||||
values(): IterableIterator<T>;
|
||||
entries(): IterableIterator<[number, T]>;
|
||||
[Symbol.iterator](): IterableIterator<T>;
|
||||
toString(): string;
|
||||
toJSON(): Array<T>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(iterable: Iterable<I> | {[key: string]: I}): LinkedList<I>;
|
||||
}
|
||||
261
backend/node_modules/mnemonist/linked-list.js
generated
vendored
Normal file
261
backend/node_modules/mnemonist/linked-list.js
generated
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
/**
|
||||
* Mnemonist Linked List
|
||||
* ======================
|
||||
*
|
||||
* Singly linked list implementation. Uses raw JavaScript objects as nodes
|
||||
* as benchmarks proved it was the fastest thing to do.
|
||||
*/
|
||||
var Iterator = require('obliterator/iterator'),
|
||||
forEach = require('obliterator/foreach');
|
||||
|
||||
/**
|
||||
* Linked List.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function LinkedList() {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the list.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
LinkedList.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.head = null;
|
||||
this.tail = null;
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the first item of the list.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
LinkedList.prototype.first = function() {
|
||||
return this.head ? this.head.item : undefined;
|
||||
};
|
||||
LinkedList.prototype.peek = LinkedList.prototype.first;
|
||||
|
||||
/**
|
||||
* Method used to get the last item of the list.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
LinkedList.prototype.last = function() {
|
||||
return this.tail ? this.tail.item : undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add an item at the end of the list.
|
||||
*
|
||||
* @param {any} item - The item to add.
|
||||
* @return {number}
|
||||
*/
|
||||
LinkedList.prototype.push = function(item) {
|
||||
var node = {item: item, next: null};
|
||||
|
||||
if (!this.head) {
|
||||
this.head = node;
|
||||
this.tail = node;
|
||||
}
|
||||
else {
|
||||
this.tail.next = node;
|
||||
this.tail = node;
|
||||
}
|
||||
|
||||
this.size++;
|
||||
|
||||
return this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add an item at the beginning of the list.
|
||||
*
|
||||
* @param {any} item - The item to add.
|
||||
* @return {number}
|
||||
*/
|
||||
LinkedList.prototype.unshift = function(item) {
|
||||
var node = {item: item, next: null};
|
||||
|
||||
if (!this.head) {
|
||||
this.head = node;
|
||||
this.tail = node;
|
||||
}
|
||||
else {
|
||||
if (!this.head.next)
|
||||
this.tail = this.head;
|
||||
node.next = this.head;
|
||||
this.head = node;
|
||||
}
|
||||
|
||||
this.size++;
|
||||
|
||||
return this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to retrieve & remove the first item of the list.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
LinkedList.prototype.shift = function() {
|
||||
if (!this.size)
|
||||
return undefined;
|
||||
|
||||
var node = this.head;
|
||||
|
||||
this.head = node.next;
|
||||
this.size--;
|
||||
|
||||
return node.item;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the list.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
LinkedList.prototype.forEach = function(callback, scope) {
|
||||
if (!this.size)
|
||||
return;
|
||||
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
var n = this.head,
|
||||
i = 0;
|
||||
|
||||
while (n) {
|
||||
callback.call(scope, n.item, i, this);
|
||||
n = n.next;
|
||||
i++;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to convert the list into an array.
|
||||
*
|
||||
* @return {array}
|
||||
*/
|
||||
LinkedList.prototype.toArray = function() {
|
||||
if (!this.size)
|
||||
return [];
|
||||
|
||||
var array = new Array(this.size);
|
||||
|
||||
for (var i = 0, l = this.size, n = this.head; i < l; i++) {
|
||||
array[i] = n.item;
|
||||
n = n.next;
|
||||
}
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a list's values.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
LinkedList.prototype.values = function() {
|
||||
var n = this.head;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (!n)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
var value = n.item;
|
||||
n = n.next;
|
||||
|
||||
return {
|
||||
value: value,
|
||||
done: false
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a list's entries.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
LinkedList.prototype.entries = function() {
|
||||
var n = this.head,
|
||||
i = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (!n)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
var value = n.item;
|
||||
n = n.next;
|
||||
i++;
|
||||
|
||||
return {
|
||||
value: [i - 1, value],
|
||||
done: false
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.values method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
LinkedList.prototype[Symbol.iterator] = LinkedList.prototype.values;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
LinkedList.prototype.toString = function() {
|
||||
return this.toArray().join(',');
|
||||
};
|
||||
|
||||
LinkedList.prototype.toJSON = function() {
|
||||
return this.toArray();
|
||||
};
|
||||
|
||||
LinkedList.prototype.inspect = function() {
|
||||
var array = this.toArray();
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(array, 'constructor', {
|
||||
value: LinkedList,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
LinkedList.prototype[Symbol.for('nodejs.util.inspect.custom')] = LinkedList.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a list.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @return {LinkedList}
|
||||
*/
|
||||
LinkedList.from = function(iterable) {
|
||||
var list = new LinkedList();
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
list.push(value);
|
||||
});
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = LinkedList;
|
||||
13
backend/node_modules/mnemonist/lru-cache-with-delete.d.ts
generated
vendored
Normal file
13
backend/node_modules/mnemonist/lru-cache-with-delete.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Mnemonist LRUCacheWithDelete Typings
|
||||
* =====================================
|
||||
*/
|
||||
import LRUCache from './lru-cache';
|
||||
|
||||
export default class LRUCacheWithDelete<K, V> extends LRUCache<K, V> {
|
||||
|
||||
delete(key: K): boolean;
|
||||
|
||||
remove<T>(key: K, missing?: T): V | T;
|
||||
|
||||
}
|
||||
287
backend/node_modules/mnemonist/lru-cache-with-delete.js
generated
vendored
Normal file
287
backend/node_modules/mnemonist/lru-cache-with-delete.js
generated
vendored
Normal file
@@ -0,0 +1,287 @@
|
||||
/**
|
||||
* Mnemonist LRUCacheWithDelete
|
||||
* =============================
|
||||
*
|
||||
* An extension of LRUCache with delete functionality.
|
||||
*/
|
||||
|
||||
var LRUCache = require('./lru-cache.js'),
|
||||
forEach = require('obliterator/foreach'),
|
||||
typed = require('./utils/typed-arrays.js'),
|
||||
iterables = require('./utils/iterables.js');
|
||||
|
||||
// The only complication with deleting items is that the LRU's
|
||||
// performance depends on having a fixed-size list of pointers; the
|
||||
// doubly-linked-list is happy to expand and contract.
|
||||
//
|
||||
// On delete, we record the position of the former item's pointer in a
|
||||
// list of "holes" in the pointer array. On insert, if there is a hole
|
||||
// the new pointer slots in to fill the hole; otherwise, it is
|
||||
// appended as usual. (Note: we are only talking here about the
|
||||
// internal pointer list. setting or getting an item promotes it
|
||||
// to the top of the LRU ranking no matter what came before)
|
||||
|
||||
function LRUCacheWithDelete(Keys, Values, capacity) {
|
||||
if (arguments.length < 2) {
|
||||
LRUCache.call(this, Keys);
|
||||
}
|
||||
else {
|
||||
LRUCache.call(this, Keys, Values, capacity);
|
||||
}
|
||||
var PointerArray = typed.getPointerArray(this.capacity);
|
||||
this.deleted = new PointerArray(this.capacity);
|
||||
this.deletedSize = 0;
|
||||
}
|
||||
|
||||
for (var k in LRUCache.prototype)
|
||||
LRUCacheWithDelete.prototype[k] = LRUCache.prototype[k];
|
||||
if (typeof Symbol !== 'undefined')
|
||||
LRUCacheWithDelete.prototype[Symbol.iterator] = LRUCache.prototype[Symbol.iterator];
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
LRUCacheWithDelete.prototype.clear = function() {
|
||||
LRUCache.prototype.clear.call(this);
|
||||
this.deletedSize = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set the value for the given key in the cache.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @param {any} value - Value.
|
||||
* @return {undefined}
|
||||
*/
|
||||
LRUCacheWithDelete.prototype.set = function(key, value) {
|
||||
|
||||
var pointer = this.items[key];
|
||||
|
||||
// The key already exists, we just need to update the value and splay on top
|
||||
if (typeof pointer !== 'undefined') {
|
||||
this.splayOnTop(pointer);
|
||||
this.V[pointer] = value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// The cache is not yet full
|
||||
if (this.size < this.capacity) {
|
||||
if (this.deletedSize > 0) {
|
||||
// If there is a "hole" in the pointer list, reuse it
|
||||
pointer = this.deleted[--this.deletedSize];
|
||||
}
|
||||
else {
|
||||
// otherwise append to the pointer list
|
||||
pointer = this.size;
|
||||
}
|
||||
this.size++;
|
||||
}
|
||||
|
||||
// Cache is full, we need to drop the last value
|
||||
else {
|
||||
pointer = this.tail;
|
||||
this.tail = this.backward[pointer];
|
||||
delete this.items[this.K[pointer]];
|
||||
}
|
||||
|
||||
// Storing key & value
|
||||
this.items[key] = pointer;
|
||||
this.K[pointer] = key;
|
||||
this.V[pointer] = value;
|
||||
|
||||
// Moving the item at the front of the list
|
||||
this.forward[pointer] = this.head;
|
||||
this.backward[this.head] = pointer;
|
||||
this.head = pointer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set the value for the given key in the cache
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @param {any} value - Value.
|
||||
* @return {{evicted: boolean, key: any, value: any}} An object containing the
|
||||
* key and value of an item that was overwritten or evicted in the set
|
||||
* operation, as well as a boolean indicating whether it was evicted due to
|
||||
* limited capacity. Return value is null if nothing was evicted or overwritten
|
||||
* during the set operation.
|
||||
*/
|
||||
LRUCacheWithDelete.prototype.setpop = function(key, value) {
|
||||
var oldValue = null;
|
||||
var oldKey = null;
|
||||
|
||||
var pointer = this.items[key];
|
||||
|
||||
// The key already exists, we just need to update the value and splay on top
|
||||
if (typeof pointer !== 'undefined') {
|
||||
this.splayOnTop(pointer);
|
||||
oldValue = this.V[pointer];
|
||||
this.V[pointer] = value;
|
||||
return {evicted: false, key: key, value: oldValue};
|
||||
}
|
||||
|
||||
// The cache is not yet full
|
||||
if (this.size < this.capacity) {
|
||||
if (this.deletedSize > 0) {
|
||||
// If there is a "hole" in the pointer list, reuse it
|
||||
pointer = this.deleted[--this.deletedSize];
|
||||
}
|
||||
else {
|
||||
// otherwise append to the pointer list
|
||||
pointer = this.size;
|
||||
}
|
||||
this.size++;
|
||||
}
|
||||
|
||||
// Cache is full, we need to drop the last value
|
||||
else {
|
||||
pointer = this.tail;
|
||||
this.tail = this.backward[pointer];
|
||||
oldValue = this.V[pointer];
|
||||
oldKey = this.K[pointer];
|
||||
delete this.items[this.K[pointer]];
|
||||
}
|
||||
|
||||
// Storing key & value
|
||||
this.items[key] = pointer;
|
||||
this.K[pointer] = key;
|
||||
this.V[pointer] = value;
|
||||
|
||||
// Moving the item at the front of the list
|
||||
this.forward[pointer] = this.head;
|
||||
this.backward[this.head] = pointer;
|
||||
this.head = pointer;
|
||||
|
||||
// Return object if eviction took place, otherwise return null
|
||||
if (oldKey) {
|
||||
return {evicted: true, key: oldKey, value: oldValue};
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to delete the entry for the given key in the cache.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @return {boolean} - true if the item was present
|
||||
*/
|
||||
LRUCacheWithDelete.prototype.delete = function(key) {
|
||||
|
||||
var pointer = this.items[key];
|
||||
|
||||
if (typeof pointer === 'undefined') {
|
||||
return false;
|
||||
}
|
||||
|
||||
delete this.items[key];
|
||||
|
||||
if (this.size === 1) {
|
||||
this.size = 0;
|
||||
this.head = 0;
|
||||
this.tail = 0;
|
||||
this.deletedSize = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
var previous = this.backward[pointer],
|
||||
next = this.forward[pointer];
|
||||
|
||||
if (this.head === pointer) {
|
||||
this.head = next;
|
||||
}
|
||||
if (this.tail === pointer) {
|
||||
this.tail = previous;
|
||||
}
|
||||
|
||||
this.forward[previous] = next;
|
||||
this.backward[next] = previous;
|
||||
|
||||
this.size--;
|
||||
this.deleted[this.deletedSize++] = pointer;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to remove and return the value for the given key in the cache.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @param {any} [missing=undefined] - Value to return if item is absent
|
||||
* @return {any} The value, if present; the missing indicator if absent
|
||||
*/
|
||||
LRUCacheWithDelete.prototype.remove = function(key, missing = undefined) {
|
||||
|
||||
var pointer = this.items[key];
|
||||
|
||||
if (typeof pointer === 'undefined') {
|
||||
return missing;
|
||||
}
|
||||
|
||||
var dead = this.V[pointer];
|
||||
delete this.items[key];
|
||||
|
||||
if (this.size === 1) {
|
||||
this.size = 0;
|
||||
this.head = 0;
|
||||
this.tail = 0;
|
||||
this.deletedSize = 0;
|
||||
return dead;
|
||||
}
|
||||
|
||||
var previous = this.backward[pointer],
|
||||
next = this.forward[pointer];
|
||||
|
||||
if (this.head === pointer) {
|
||||
this.head = next;
|
||||
}
|
||||
if (this.tail === pointer) {
|
||||
this.tail = previous;
|
||||
}
|
||||
|
||||
this.forward[previous] = next;
|
||||
this.backward[next] = previous;
|
||||
|
||||
this.size--;
|
||||
this.deleted[this.deletedSize++] = pointer;
|
||||
|
||||
return dead;
|
||||
};
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a structure.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {function} Keys - Array class for storing keys.
|
||||
* @param {function} Values - Array class for storing values.
|
||||
* @param {number} capacity - Cache's capacity.
|
||||
* @return {LRUCacheWithDelete}
|
||||
*/
|
||||
LRUCacheWithDelete.from = function(iterable, Keys, Values, capacity) {
|
||||
if (arguments.length < 2) {
|
||||
capacity = iterables.guessLength(iterable);
|
||||
|
||||
if (typeof capacity !== 'number')
|
||||
throw new Error('mnemonist/lru-cache.from: could not guess iterable length. Please provide desired capacity as last argument.');
|
||||
}
|
||||
else if (arguments.length === 2) {
|
||||
capacity = Keys;
|
||||
Keys = null;
|
||||
Values = null;
|
||||
}
|
||||
|
||||
var cache = new LRUCacheWithDelete(Keys, Values, capacity);
|
||||
|
||||
forEach(iterable, function(value, key) {
|
||||
cache.set(key, value);
|
||||
});
|
||||
|
||||
return cache;
|
||||
};
|
||||
|
||||
module.exports = LRUCacheWithDelete;
|
||||
43
backend/node_modules/mnemonist/lru-cache.d.ts
generated
vendored
Normal file
43
backend/node_modules/mnemonist/lru-cache.d.ts
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Mnemonist LRUCache Typings
|
||||
* ===========================
|
||||
*/
|
||||
import {IArrayLikeConstructor} from './utils/types';
|
||||
|
||||
export default class LRUCache<K, V> implements Iterable<[K, V]> {
|
||||
|
||||
// Members
|
||||
capacity: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(capacity: number);
|
||||
constructor(KeyArrayClass: IArrayLikeConstructor, ValueArrayClass: IArrayLikeConstructor, capacity: number);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
set(key: K, value: V): this;
|
||||
setpop(key: K, value: V): {evicted: boolean, key: K, value: V};
|
||||
get(key: K): V | undefined;
|
||||
peek(key: K): V | undefined;
|
||||
has(key: K): boolean;
|
||||
forEach(callback: (value: V, key: K, cache: this) => void, scope?: any): void;
|
||||
keys(): IterableIterator<K>;
|
||||
values(): IterableIterator<V>;
|
||||
entries(): IterableIterator<[K, V]>;
|
||||
[Symbol.iterator](): IterableIterator<[K, V]>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I, J>(
|
||||
iterable: Iterable<[I, J]> | {[key: string]: J},
|
||||
KeyArrayClass: IArrayLikeConstructor,
|
||||
ValueArrayClass: IArrayLikeConstructor,
|
||||
capacity?: number
|
||||
): LRUCache<I, J>;
|
||||
|
||||
static from<I, J>(
|
||||
iterable: Iterable<[I, J]> | {[key: string]: J},
|
||||
capacity?: number
|
||||
): LRUCache<I, J>;
|
||||
}
|
||||
436
backend/node_modules/mnemonist/lru-cache.js
generated
vendored
Normal file
436
backend/node_modules/mnemonist/lru-cache.js
generated
vendored
Normal file
@@ -0,0 +1,436 @@
|
||||
/**
|
||||
* Mnemonist LRUCache
|
||||
* ===================
|
||||
*
|
||||
* JavaScript implementation of the LRU Cache data structure. To save up
|
||||
* memory and allocations this implementation represents its underlying
|
||||
* doubly-linked list as static arrays and pointers. Thus, memory is allocated
|
||||
* only once at instantiation and JS objects are never created to serve as
|
||||
* pointers. This also means this implementation does not trigger too many
|
||||
* garbage collections.
|
||||
*
|
||||
* Note that to save up memory, a LRU Cache can be implemented using a singly
|
||||
* linked list by storing predecessors' pointers as hashmap values.
|
||||
* However, this means more hashmap lookups and would probably slow the whole
|
||||
* thing down. What's more, pointers are not the things taking most space in
|
||||
* memory.
|
||||
*/
|
||||
var Iterator = require('obliterator/iterator'),
|
||||
forEach = require('obliterator/foreach'),
|
||||
typed = require('./utils/typed-arrays.js'),
|
||||
iterables = require('./utils/iterables.js');
|
||||
|
||||
/**
|
||||
* LRUCache.
|
||||
*
|
||||
* @constructor
|
||||
* @param {function} Keys - Array class for storing keys.
|
||||
* @param {function} Values - Array class for storing values.
|
||||
* @param {number} capacity - Desired capacity.
|
||||
*/
|
||||
function LRUCache(Keys, Values, capacity) {
|
||||
if (arguments.length < 2) {
|
||||
capacity = Keys;
|
||||
Keys = null;
|
||||
Values = null;
|
||||
}
|
||||
|
||||
this.capacity = capacity;
|
||||
|
||||
if (typeof this.capacity !== 'number' || this.capacity <= 0)
|
||||
throw new Error('mnemonist/lru-cache: capacity should be positive number.');
|
||||
else if (!isFinite(this.capacity) || Math.floor(this.capacity) !== this.capacity)
|
||||
throw new Error('mnemonist/lru-cache: capacity should be a finite positive integer.');
|
||||
|
||||
var PointerArray = typed.getPointerArray(capacity);
|
||||
|
||||
this.forward = new PointerArray(capacity);
|
||||
this.backward = new PointerArray(capacity);
|
||||
this.K = typeof Keys === 'function' ? new Keys(capacity) : new Array(capacity);
|
||||
this.V = typeof Values === 'function' ? new Values(capacity) : new Array(capacity);
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
this.head = 0;
|
||||
this.tail = 0;
|
||||
this.items = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
LRUCache.prototype.clear = function() {
|
||||
this.size = 0;
|
||||
this.head = 0;
|
||||
this.tail = 0;
|
||||
this.items = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to splay a value on top.
|
||||
*
|
||||
* @param {number} pointer - Pointer of the value to splay on top.
|
||||
* @return {LRUCache}
|
||||
*/
|
||||
LRUCache.prototype.splayOnTop = function(pointer) {
|
||||
var oldHead = this.head;
|
||||
|
||||
if (this.head === pointer)
|
||||
return this;
|
||||
|
||||
var previous = this.backward[pointer],
|
||||
next = this.forward[pointer];
|
||||
|
||||
if (this.tail === pointer) {
|
||||
this.tail = previous;
|
||||
}
|
||||
else {
|
||||
this.backward[next] = previous;
|
||||
}
|
||||
|
||||
this.forward[previous] = next;
|
||||
|
||||
this.backward[oldHead] = pointer;
|
||||
this.head = pointer;
|
||||
this.forward[pointer] = oldHead;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set the value for the given key in the cache.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @param {any} value - Value.
|
||||
* @return {undefined}
|
||||
*/
|
||||
LRUCache.prototype.set = function(key, value) {
|
||||
|
||||
var pointer = this.items[key];
|
||||
|
||||
// The key already exists, we just need to update the value and splay on top
|
||||
if (typeof pointer !== 'undefined') {
|
||||
this.splayOnTop(pointer);
|
||||
this.V[pointer] = value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// The cache is not yet full
|
||||
if (this.size < this.capacity) {
|
||||
pointer = this.size++;
|
||||
}
|
||||
|
||||
// Cache is full, we need to drop the last value
|
||||
else {
|
||||
pointer = this.tail;
|
||||
this.tail = this.backward[pointer];
|
||||
delete this.items[this.K[pointer]];
|
||||
}
|
||||
|
||||
// Storing key & value
|
||||
this.items[key] = pointer;
|
||||
this.K[pointer] = key;
|
||||
this.V[pointer] = value;
|
||||
|
||||
// Moving the item at the front of the list
|
||||
this.forward[pointer] = this.head;
|
||||
this.backward[this.head] = pointer;
|
||||
this.head = pointer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set the value for the given key in the cache
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @param {any} value - Value.
|
||||
* @return {{evicted: boolean, key: any, value: any}} An object containing the
|
||||
* key and value of an item that was overwritten or evicted in the set
|
||||
* operation, as well as a boolean indicating whether it was evicted due to
|
||||
* limited capacity. Return value is null if nothing was evicted or overwritten
|
||||
* during the set operation.
|
||||
*/
|
||||
LRUCache.prototype.setpop = function(key, value) {
|
||||
var oldValue = null;
|
||||
var oldKey = null;
|
||||
|
||||
var pointer = this.items[key];
|
||||
|
||||
// The key already exists, we just need to update the value and splay on top
|
||||
if (typeof pointer !== 'undefined') {
|
||||
this.splayOnTop(pointer);
|
||||
oldValue = this.V[pointer];
|
||||
this.V[pointer] = value;
|
||||
return {evicted: false, key: key, value: oldValue};
|
||||
}
|
||||
|
||||
// The cache is not yet full
|
||||
if (this.size < this.capacity) {
|
||||
pointer = this.size++;
|
||||
}
|
||||
|
||||
// Cache is full, we need to drop the last value
|
||||
else {
|
||||
pointer = this.tail;
|
||||
this.tail = this.backward[pointer];
|
||||
oldValue = this.V[pointer];
|
||||
oldKey = this.K[pointer];
|
||||
delete this.items[this.K[pointer]];
|
||||
}
|
||||
|
||||
// Storing key & value
|
||||
this.items[key] = pointer;
|
||||
this.K[pointer] = key;
|
||||
this.V[pointer] = value;
|
||||
|
||||
// Moving the item at the front of the list
|
||||
this.forward[pointer] = this.head;
|
||||
this.backward[this.head] = pointer;
|
||||
this.head = pointer;
|
||||
|
||||
// Return object if eviction took place, otherwise return null
|
||||
if (oldKey) {
|
||||
return {evicted: true, key: oldKey, value: oldValue};
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to check whether the key exists in the cache.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @return {boolean}
|
||||
*/
|
||||
LRUCache.prototype.has = function(key) {
|
||||
return key in this.items;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the value attached to the given key. Will move the
|
||||
* related key to the front of the underlying linked list.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @return {any}
|
||||
*/
|
||||
LRUCache.prototype.get = function(key) {
|
||||
var pointer = this.items[key];
|
||||
|
||||
if (typeof pointer === 'undefined')
|
||||
return;
|
||||
|
||||
this.splayOnTop(pointer);
|
||||
|
||||
return this.V[pointer];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the value attached to the given key. Does not modify
|
||||
* the ordering of the underlying linked list.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @return {any}
|
||||
*/
|
||||
LRUCache.prototype.peek = function(key) {
|
||||
var pointer = this.items[key];
|
||||
|
||||
if (typeof pointer === 'undefined')
|
||||
return;
|
||||
|
||||
return this.V[pointer];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the cache's entries using a callback.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
LRUCache.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
var i = 0,
|
||||
l = this.size;
|
||||
|
||||
var pointer = this.head,
|
||||
keys = this.K,
|
||||
values = this.V,
|
||||
forward = this.forward;
|
||||
|
||||
while (i < l) {
|
||||
|
||||
callback.call(scope, values[pointer], keys[pointer], this);
|
||||
pointer = forward[pointer];
|
||||
|
||||
i++;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over the cache's keys from most
|
||||
* recently used to least recently used.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
LRUCache.prototype.keys = function() {
|
||||
var i = 0,
|
||||
l = this.size;
|
||||
|
||||
var pointer = this.head,
|
||||
keys = this.K,
|
||||
forward = this.forward;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= l)
|
||||
return {done: true};
|
||||
|
||||
var key = keys[pointer];
|
||||
|
||||
i++;
|
||||
|
||||
if (i < l)
|
||||
pointer = forward[pointer];
|
||||
|
||||
return {
|
||||
done: false,
|
||||
value: key
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over the cache's values from most
|
||||
* recently used to least recently used.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
LRUCache.prototype.values = function() {
|
||||
var i = 0,
|
||||
l = this.size;
|
||||
|
||||
var pointer = this.head,
|
||||
values = this.V,
|
||||
forward = this.forward;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= l)
|
||||
return {done: true};
|
||||
|
||||
var value = values[pointer];
|
||||
|
||||
i++;
|
||||
|
||||
if (i < l)
|
||||
pointer = forward[pointer];
|
||||
|
||||
return {
|
||||
done: false,
|
||||
value: value
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over the cache's entries from most
|
||||
* recently used to least recently used.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
LRUCache.prototype.entries = function() {
|
||||
var i = 0,
|
||||
l = this.size;
|
||||
|
||||
var pointer = this.head,
|
||||
keys = this.K,
|
||||
values = this.V,
|
||||
forward = this.forward;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= l)
|
||||
return {done: true};
|
||||
|
||||
var key = keys[pointer],
|
||||
value = values[pointer];
|
||||
|
||||
i++;
|
||||
|
||||
if (i < l)
|
||||
pointer = forward[pointer];
|
||||
|
||||
return {
|
||||
done: false,
|
||||
value: [key, value]
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.entries method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
LRUCache.prototype[Symbol.iterator] = LRUCache.prototype.entries;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
LRUCache.prototype.inspect = function() {
|
||||
var proxy = new Map();
|
||||
|
||||
var iterator = this.entries(),
|
||||
step;
|
||||
|
||||
while ((step = iterator.next(), !step.done))
|
||||
proxy.set(step.value[0], step.value[1]);
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: LRUCache,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
LRUCache.prototype[Symbol.for('nodejs.util.inspect.custom')] = LRUCache.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a structure.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {function} Keys - Array class for storing keys.
|
||||
* @param {function} Values - Array class for storing values.
|
||||
* @param {number} capacity - Cache's capacity.
|
||||
* @return {LRUCache}
|
||||
*/
|
||||
LRUCache.from = function(iterable, Keys, Values, capacity) {
|
||||
if (arguments.length < 2) {
|
||||
capacity = iterables.guessLength(iterable);
|
||||
|
||||
if (typeof capacity !== 'number')
|
||||
throw new Error('mnemonist/lru-cache.from: could not guess iterable length. Please provide desired capacity as last argument.');
|
||||
}
|
||||
else if (arguments.length === 2) {
|
||||
capacity = Keys;
|
||||
Keys = null;
|
||||
Values = null;
|
||||
}
|
||||
|
||||
var cache = new LRUCache(Keys, Values, capacity);
|
||||
|
||||
forEach(iterable, function(value, key) {
|
||||
cache.set(key, value);
|
||||
});
|
||||
|
||||
return cache;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = LRUCache;
|
||||
13
backend/node_modules/mnemonist/lru-map-with-delete.d.ts
generated
vendored
Normal file
13
backend/node_modules/mnemonist/lru-map-with-delete.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Mnemonist LRUMapWithDelete Typings
|
||||
* ===================================
|
||||
*/
|
||||
import LRUMap from './lru-map';
|
||||
|
||||
export default class LRUMapWithDelete<K, V> extends LRUMap<K, V> {
|
||||
|
||||
delete(key: K): boolean;
|
||||
|
||||
remove<T>(key: K, missing?: T): V | T;
|
||||
|
||||
}
|
||||
287
backend/node_modules/mnemonist/lru-map-with-delete.js
generated
vendored
Normal file
287
backend/node_modules/mnemonist/lru-map-with-delete.js
generated
vendored
Normal file
@@ -0,0 +1,287 @@
|
||||
/**
|
||||
* Mnemonist LRUMapWithDelete
|
||||
* ===========================
|
||||
*
|
||||
* An extension of LRUMap with delete functionality.
|
||||
*/
|
||||
|
||||
var LRUMap = require('./lru-map.js'),
|
||||
forEach = require('obliterator/foreach'),
|
||||
typed = require('./utils/typed-arrays.js'),
|
||||
iterables = require('./utils/iterables.js');
|
||||
|
||||
// The only complication with deleting items is that the LRU's
|
||||
// performance depends on having a fixed-size list of pointers; the
|
||||
// doubly-linked-list is happy to expand and contract.
|
||||
//
|
||||
// On delete, we record the position of the former item's pointer in a
|
||||
// list of "holes" in the pointer array. On insert, if there is a hole
|
||||
// the new pointer slots in to fill the hole; otherwise, it is
|
||||
// appended as usual. (Note: we are only talking here about the
|
||||
// internal pointer list. setting or getting an item promotes it
|
||||
// to the top of the LRU ranking no matter what came before)
|
||||
|
||||
function LRUMapWithDelete(Keys, Values, capacity) {
|
||||
if (arguments.length < 2) {
|
||||
LRUMap.call(this, Keys);
|
||||
}
|
||||
else {
|
||||
LRUMap.call(this, Keys, Values, capacity);
|
||||
}
|
||||
var PointerArray = typed.getPointerArray(this.capacity);
|
||||
this.deleted = new PointerArray(this.capacity);
|
||||
this.deletedSize = 0;
|
||||
}
|
||||
|
||||
for (var k in LRUMap.prototype)
|
||||
LRUMapWithDelete.prototype[k] = LRUMap.prototype[k];
|
||||
if (typeof Symbol !== 'undefined')
|
||||
LRUMapWithDelete.prototype[Symbol.iterator] = LRUMap.prototype[Symbol.iterator];
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
LRUMapWithDelete.prototype.clear = function() {
|
||||
LRUMap.prototype.clear.call(this);
|
||||
this.deletedSize = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set the value for the given key in the cache.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @param {any} value - Value.
|
||||
* @return {undefined}
|
||||
*/
|
||||
LRUMapWithDelete.prototype.set = function(key, value) {
|
||||
|
||||
var pointer = this.items.get(key);
|
||||
|
||||
// The key already exists, we just need to update the value and splay on top
|
||||
if (typeof pointer !== 'undefined') {
|
||||
this.splayOnTop(pointer);
|
||||
this.V[pointer] = value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// The cache is not yet full
|
||||
if (this.size < this.capacity) {
|
||||
if (this.deletedSize > 0) {
|
||||
// If there is a "hole" in the pointer list, reuse it
|
||||
pointer = this.deleted[--this.deletedSize];
|
||||
}
|
||||
else {
|
||||
// otherwise append to the pointer list
|
||||
pointer = this.size;
|
||||
}
|
||||
this.size++;
|
||||
}
|
||||
|
||||
// Cache is full, we need to drop the last value
|
||||
else {
|
||||
pointer = this.tail;
|
||||
this.tail = this.backward[pointer];
|
||||
this.items.delete(this.K[pointer]);
|
||||
}
|
||||
|
||||
// Storing key & value
|
||||
this.items.set(key, pointer);
|
||||
this.K[pointer] = key;
|
||||
this.V[pointer] = value;
|
||||
|
||||
// Moving the item at the front of the list
|
||||
this.forward[pointer] = this.head;
|
||||
this.backward[this.head] = pointer;
|
||||
this.head = pointer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set the value for the given key in the cache
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @param {any} value - Value.
|
||||
* @return {{evicted: boolean, key: any, value: any}} An object containing the
|
||||
* key and value of an item that was overwritten or evicted in the set
|
||||
* operation, as well as a boolean indicating whether it was evicted due to
|
||||
* limited capacity. Return value is null if nothing was evicted or overwritten
|
||||
* during the set operation.
|
||||
*/
|
||||
LRUMapWithDelete.prototype.setpop = function(key, value) {
|
||||
var oldValue = null;
|
||||
var oldKey = null;
|
||||
|
||||
var pointer = this.items.get(key);
|
||||
|
||||
// The key already exists, we just need to update the value and splay on top
|
||||
if (typeof pointer !== 'undefined') {
|
||||
this.splayOnTop(pointer);
|
||||
oldValue = this.V[pointer];
|
||||
this.V[pointer] = value;
|
||||
return {evicted: false, key: key, value: oldValue};
|
||||
}
|
||||
|
||||
// The cache is not yet full
|
||||
if (this.size < this.capacity) {
|
||||
if (this.deletedSize > 0) {
|
||||
// If there is a "hole" in the pointer list, reuse it
|
||||
pointer = this.deleted[--this.deletedSize];
|
||||
}
|
||||
else {
|
||||
// otherwise append to the pointer list
|
||||
pointer = this.size;
|
||||
}
|
||||
this.size++;
|
||||
}
|
||||
|
||||
// Cache is full, we need to drop the last value
|
||||
else {
|
||||
pointer = this.tail;
|
||||
this.tail = this.backward[pointer];
|
||||
oldValue = this.V[pointer];
|
||||
oldKey = this.K[pointer];
|
||||
this.items.delete(this.K[pointer]);
|
||||
}
|
||||
|
||||
// Storing key & value
|
||||
this.items.set(key, pointer);
|
||||
this.K[pointer] = key;
|
||||
this.V[pointer] = value;
|
||||
|
||||
// Moving the item at the front of the list
|
||||
this.forward[pointer] = this.head;
|
||||
this.backward[this.head] = pointer;
|
||||
this.head = pointer;
|
||||
|
||||
// Return object if eviction took place, otherwise return null
|
||||
if (oldKey) {
|
||||
return {evicted: true, key: oldKey, value: oldValue};
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to delete the entry for the given key in the cache.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @return {boolean} - true if the item was present
|
||||
*/
|
||||
LRUMapWithDelete.prototype.delete = function(key) {
|
||||
|
||||
var pointer = this.items.get(key);
|
||||
|
||||
if (typeof pointer === 'undefined') {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.items.delete(key);
|
||||
|
||||
if (this.size === 1) {
|
||||
this.size = 0;
|
||||
this.head = 0;
|
||||
this.tail = 0;
|
||||
this.deletedSize = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
var previous = this.backward[pointer],
|
||||
next = this.forward[pointer];
|
||||
|
||||
if (this.head === pointer) {
|
||||
this.head = next;
|
||||
}
|
||||
if (this.tail === pointer) {
|
||||
this.tail = previous;
|
||||
}
|
||||
|
||||
this.forward[previous] = next;
|
||||
this.backward[next] = previous;
|
||||
|
||||
this.size--;
|
||||
this.deleted[this.deletedSize++] = pointer;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to remove and return the value for the given key in the cache.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @param {any} [missing=undefined] - Value to return if item is absent
|
||||
* @return {any} The value, if present; the missing indicator if absent
|
||||
*/
|
||||
LRUMapWithDelete.prototype.remove = function(key, missing = undefined) {
|
||||
|
||||
var pointer = this.items.get(key);
|
||||
|
||||
if (typeof pointer === 'undefined') {
|
||||
return missing;
|
||||
}
|
||||
|
||||
var dead = this.V[pointer];
|
||||
this.items.delete(key);
|
||||
|
||||
if (this.size === 1) {
|
||||
this.size = 0;
|
||||
this.head = 0;
|
||||
this.tail = 0;
|
||||
this.deletedSize = 0;
|
||||
return dead;
|
||||
}
|
||||
|
||||
var previous = this.backward[pointer],
|
||||
next = this.forward[pointer];
|
||||
|
||||
if (this.head === pointer) {
|
||||
this.head = next;
|
||||
}
|
||||
if (this.tail === pointer) {
|
||||
this.tail = previous;
|
||||
}
|
||||
|
||||
this.forward[previous] = next;
|
||||
this.backward[next] = previous;
|
||||
|
||||
this.size--;
|
||||
this.deleted[this.deletedSize++] = pointer;
|
||||
|
||||
return dead;
|
||||
};
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a structure.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {function} Keys - Array class for storing keys.
|
||||
* @param {function} Values - Array class for storing values.
|
||||
* @param {number} capacity - Cache's capacity.
|
||||
* @return {LRUMapWithDelete}
|
||||
*/
|
||||
LRUMapWithDelete.from = function(iterable, Keys, Values, capacity) {
|
||||
if (arguments.length < 2) {
|
||||
capacity = iterables.guessLength(iterable);
|
||||
|
||||
if (typeof capacity !== 'number')
|
||||
throw new Error('mnemonist/lru-map.from: could not guess iterable length. Please provide desired capacity as last argument.');
|
||||
}
|
||||
else if (arguments.length === 2) {
|
||||
capacity = Keys;
|
||||
Keys = null;
|
||||
Values = null;
|
||||
}
|
||||
|
||||
var cache = new LRUMapWithDelete(Keys, Values, capacity);
|
||||
|
||||
forEach(iterable, function(value, key) {
|
||||
cache.set(key, value);
|
||||
});
|
||||
|
||||
return cache;
|
||||
};
|
||||
|
||||
module.exports = LRUMapWithDelete;
|
||||
43
backend/node_modules/mnemonist/lru-map.d.ts
generated
vendored
Normal file
43
backend/node_modules/mnemonist/lru-map.d.ts
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Mnemonist LRUMap Typings
|
||||
* =========================
|
||||
*/
|
||||
import {IArrayLikeConstructor} from './utils/types';
|
||||
|
||||
export default class LRUMap<K, V> implements Iterable<[K, V]> {
|
||||
|
||||
// Members
|
||||
capacity: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(capacity: number);
|
||||
constructor(KeyArrayClass: IArrayLikeConstructor, ValueArrayClass: IArrayLikeConstructor, capacity: number);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
set(key: K, value: V): this;
|
||||
setpop(key: K, value: V): {evicted: boolean, key: K, value: V};
|
||||
get(key: K): V | undefined;
|
||||
peek(key: K): V | undefined;
|
||||
has(key: K): boolean;
|
||||
forEach(callback: (value: V, key: K, cache: this) => void, scope?: any): void;
|
||||
keys(): IterableIterator<K>;
|
||||
values(): IterableIterator<V>;
|
||||
entries(): IterableIterator<[K, V]>;
|
||||
[Symbol.iterator](): IterableIterator<[K, V]>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I, J>(
|
||||
iterable: Iterable<[I, J]> | {[key: string]: J},
|
||||
KeyArrayClass: IArrayLikeConstructor,
|
||||
ValueArrayClass: IArrayLikeConstructor,
|
||||
capacity?: number
|
||||
): LRUMap<I, J>;
|
||||
|
||||
static from<I, J>(
|
||||
iterable: Iterable<[I, J]> | {[key: string]: J},
|
||||
capacity?: number
|
||||
): LRUMap<I, J>;
|
||||
}
|
||||
261
backend/node_modules/mnemonist/lru-map.js
generated
vendored
Normal file
261
backend/node_modules/mnemonist/lru-map.js
generated
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
/**
|
||||
* Mnemonist LRUMap
|
||||
* =================
|
||||
*
|
||||
* Variant of the LRUCache class that leverages an ES6 Map instead of an object.
|
||||
* It might be faster for some use case but it is still hard to understand
|
||||
* when a Map can outperform an object in v8.
|
||||
*/
|
||||
var LRUCache = require('./lru-cache.js'),
|
||||
forEach = require('obliterator/foreach'),
|
||||
typed = require('./utils/typed-arrays.js'),
|
||||
iterables = require('./utils/iterables.js');
|
||||
|
||||
/**
|
||||
* LRUMap.
|
||||
*
|
||||
* @constructor
|
||||
* @param {function} Keys - Array class for storing keys.
|
||||
* @param {function} Values - Array class for storing values.
|
||||
* @param {number} capacity - Desired capacity.
|
||||
*/
|
||||
function LRUMap(Keys, Values, capacity) {
|
||||
if (arguments.length < 2) {
|
||||
capacity = Keys;
|
||||
Keys = null;
|
||||
Values = null;
|
||||
}
|
||||
|
||||
this.capacity = capacity;
|
||||
|
||||
if (typeof this.capacity !== 'number' || this.capacity <= 0)
|
||||
throw new Error('mnemonist/lru-map: capacity should be positive number.');
|
||||
else if (!isFinite(this.capacity) || Math.floor(this.capacity) !== this.capacity)
|
||||
throw new Error('mnemonist/lru-map: capacity should be a finite positive integer.');
|
||||
|
||||
var PointerArray = typed.getPointerArray(capacity);
|
||||
|
||||
this.forward = new PointerArray(capacity);
|
||||
this.backward = new PointerArray(capacity);
|
||||
this.K = typeof Keys === 'function' ? new Keys(capacity) : new Array(capacity);
|
||||
this.V = typeof Values === 'function' ? new Values(capacity) : new Array(capacity);
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
this.head = 0;
|
||||
this.tail = 0;
|
||||
this.items = new Map();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
LRUMap.prototype.clear = function() {
|
||||
this.size = 0;
|
||||
this.head = 0;
|
||||
this.tail = 0;
|
||||
this.items.clear();
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set the value for the given key in the cache.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @param {any} value - Value.
|
||||
* @return {undefined}
|
||||
*/
|
||||
LRUMap.prototype.set = function(key, value) {
|
||||
|
||||
var pointer = this.items.get(key);
|
||||
|
||||
// The key already exists, we just need to update the value and splay on top
|
||||
if (typeof pointer !== 'undefined') {
|
||||
this.splayOnTop(pointer);
|
||||
this.V[pointer] = value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// The cache is not yet full
|
||||
if (this.size < this.capacity) {
|
||||
pointer = this.size++;
|
||||
}
|
||||
|
||||
// Cache is full, we need to drop the last value
|
||||
else {
|
||||
pointer = this.tail;
|
||||
this.tail = this.backward[pointer];
|
||||
this.items.delete(this.K[pointer]);
|
||||
}
|
||||
|
||||
// Storing key & value
|
||||
this.items.set(key, pointer);
|
||||
this.K[pointer] = key;
|
||||
this.V[pointer] = value;
|
||||
|
||||
// Moving the item at the front of the list
|
||||
this.forward[pointer] = this.head;
|
||||
this.backward[this.head] = pointer;
|
||||
this.head = pointer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set the value for the given key in the cache.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @param {any} value - Value.
|
||||
* @return {{evicted: boolean, key: any, value: any}} An object containing the
|
||||
* key and value of an item that was overwritten or evicted in the set
|
||||
* operation, as well as a boolean indicating whether it was evicted due to
|
||||
* limited capacity. Return value is null if nothing was evicted or overwritten
|
||||
* during the set operation.
|
||||
*/
|
||||
LRUMap.prototype.setpop = function(key, value) {
|
||||
var oldValue = null;
|
||||
var oldKey = null;
|
||||
|
||||
var pointer = this.items.get(key);
|
||||
|
||||
// The key already exists, we just need to update the value and splay on top
|
||||
if (typeof pointer !== 'undefined') {
|
||||
this.splayOnTop(pointer);
|
||||
oldValue = this.V[pointer];
|
||||
this.V[pointer] = value;
|
||||
return {evicted: false, key: key, value: oldValue};
|
||||
}
|
||||
|
||||
// The cache is not yet full
|
||||
if (this.size < this.capacity) {
|
||||
pointer = this.size++;
|
||||
}
|
||||
|
||||
// Cache is full, we need to drop the last value
|
||||
else {
|
||||
pointer = this.tail;
|
||||
this.tail = this.backward[pointer];
|
||||
oldValue = this.V[pointer];
|
||||
oldKey = this.K[pointer];
|
||||
this.items.delete(this.K[pointer]);
|
||||
}
|
||||
|
||||
// Storing key & value
|
||||
this.items.set(key, pointer);
|
||||
this.K[pointer] = key;
|
||||
this.V[pointer] = value;
|
||||
|
||||
// Moving the item at the front of the list
|
||||
this.forward[pointer] = this.head;
|
||||
this.backward[this.head] = pointer;
|
||||
this.head = pointer;
|
||||
|
||||
// Return object if eviction took place, otherwise return null
|
||||
if (oldKey) {
|
||||
return {evicted: true, key: oldKey, value: oldValue};
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to check whether the key exists in the cache.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @return {boolean}
|
||||
*/
|
||||
LRUMap.prototype.has = function(key) {
|
||||
return this.items.has(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the value attached to the given key. Will move the
|
||||
* related key to the front of the underlying linked list.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @return {any}
|
||||
*/
|
||||
LRUMap.prototype.get = function(key) {
|
||||
var pointer = this.items.get(key);
|
||||
|
||||
if (typeof pointer === 'undefined')
|
||||
return;
|
||||
|
||||
this.splayOnTop(pointer);
|
||||
|
||||
return this.V[pointer];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the value attached to the given key. Does not modify
|
||||
* the ordering of the underlying linked list.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @return {any}
|
||||
*/
|
||||
LRUMap.prototype.peek = function(key) {
|
||||
var pointer = this.items.get(key);
|
||||
|
||||
if (typeof pointer === 'undefined')
|
||||
return;
|
||||
|
||||
return this.V[pointer];
|
||||
};
|
||||
|
||||
/**
|
||||
* Methods that can be reused as-is from LRUCache.
|
||||
*/
|
||||
LRUMap.prototype.splayOnTop = LRUCache.prototype.splayOnTop;
|
||||
LRUMap.prototype.forEach = LRUCache.prototype.forEach;
|
||||
LRUMap.prototype.keys = LRUCache.prototype.keys;
|
||||
LRUMap.prototype.values = LRUCache.prototype.values;
|
||||
LRUMap.prototype.entries = LRUCache.prototype.entries;
|
||||
|
||||
/**
|
||||
* Attaching the #.entries method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
LRUMap.prototype[Symbol.iterator] = LRUMap.prototype.entries;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
LRUMap.prototype.inspect = LRUCache.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a structure.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {function} Keys - Array class for storing keys.
|
||||
* @param {function} Values - Array class for storing values.
|
||||
* @param {number} capacity - Cache's capacity.
|
||||
* @return {LRUMap}
|
||||
*/
|
||||
LRUMap.from = function(iterable, Keys, Values, capacity) {
|
||||
if (arguments.length < 2) {
|
||||
capacity = iterables.guessLength(iterable);
|
||||
|
||||
if (typeof capacity !== 'number')
|
||||
throw new Error('mnemonist/lru-cache.from: could not guess iterable length. Please provide desired capacity as last argument.');
|
||||
}
|
||||
else if (arguments.length === 2) {
|
||||
capacity = Keys;
|
||||
Keys = null;
|
||||
Values = null;
|
||||
}
|
||||
|
||||
var cache = new LRUMap(Keys, Values, capacity);
|
||||
|
||||
forEach(iterable, function(value, key) {
|
||||
cache.set(key, value);
|
||||
});
|
||||
|
||||
return cache;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = LRUMap;
|
||||
447
backend/node_modules/mnemonist/multi-array.js
generated
vendored
Normal file
447
backend/node_modules/mnemonist/multi-array.js
generated
vendored
Normal file
@@ -0,0 +1,447 @@
|
||||
/**
|
||||
* Mnemonist MultiArray
|
||||
* =====================
|
||||
*
|
||||
* Memory-efficient representation of an array of arrays. In JavaScript and
|
||||
* most high-level languages, creating objects has a cost. This implementation
|
||||
* is therefore able to represent nested containers without needing to create
|
||||
* objects. This works by storing singly linked lists in a single flat array.
|
||||
* However, this means that this structure comes with some read/write
|
||||
* overhead but consume very few memory.
|
||||
*
|
||||
* This structure should be particularly suited to indices that will need to
|
||||
* merge arrays anyway when queried and that are quite heavily hit (such as
|
||||
* an inverted index or a quad tree).
|
||||
*
|
||||
* Note: the implementation does not require to keep track of head pointers
|
||||
* but this comes with some advantages such as not needing to offset pointers
|
||||
* by 1 and being able to perform in-order iteration. This remains quite lean
|
||||
* in memory and does not hinder performance whatsoever.
|
||||
*/
|
||||
var typed = require('./utils/typed-arrays.js'),
|
||||
Vector = require('./vector.js'),
|
||||
Iterator = require('obliterator/iterator');
|
||||
|
||||
var PointerVector = Vector.PointerVector;
|
||||
|
||||
/**
|
||||
* MultiArray.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function MultiArray(Container, capacity) {
|
||||
this.capacity = capacity || null;
|
||||
this.Container = Container || Array;
|
||||
this.hasFixedCapacity = this.capacity !== null;
|
||||
|
||||
if (typeof this.Container !== 'function')
|
||||
throw new Error('mnemonist/multi-array.constructor: container should be a function.');
|
||||
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
MultiArray.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
this.dimension = 0;
|
||||
|
||||
// NOTE: #.heads, #.tails & #.lengths have a length equal to the dimension of
|
||||
// the array, while #.pointers has a length equal to its size.
|
||||
|
||||
// Storage
|
||||
if (this.hasFixedCapacity) {
|
||||
var capacity = this.capacity;
|
||||
|
||||
var PointerArray = typed.getPointerArray(capacity);
|
||||
|
||||
var policy = function(currentCapacity) {
|
||||
var newCapacity = Math.max(1, Math.ceil(currentCapacity * 1.5));
|
||||
|
||||
// Clamping max allocation
|
||||
return Math.min(newCapacity, capacity);
|
||||
};
|
||||
|
||||
var initialCapacity = Math.max(8, capacity);
|
||||
|
||||
this.tails = new Vector(PointerArray, {policy: policy, initialCapacity: initialCapacity});
|
||||
this.lengths = new Vector(PointerArray, {policy: policy, initialCapacity: initialCapacity});
|
||||
this.pointers = new PointerArray(capacity);
|
||||
|
||||
this.items = new this.Container(capacity);
|
||||
}
|
||||
else {
|
||||
|
||||
this.tails = new PointerVector();
|
||||
this.lengths = new PointerVector();
|
||||
this.pointers = new PointerVector();
|
||||
|
||||
this.items = new this.Container();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add an item to the container at the given index.
|
||||
*
|
||||
* @param {number} index - Index of the container.
|
||||
* @param {any} item - Item to add.
|
||||
* @return {MultiArray}
|
||||
*/
|
||||
MultiArray.prototype.set = function(index, item) {
|
||||
var pointer = this.size;
|
||||
|
||||
// TODO: this can be factorized!
|
||||
|
||||
if (this.hasFixedCapacity) {
|
||||
|
||||
if (index >= this.capacity || this.size === this.capacity)
|
||||
throw new Error('mnemonist/multi-array: attempting to allocate further than capacity.');
|
||||
|
||||
// This linked list does not exist yet. Let's create it
|
||||
if (index >= this.dimension) {
|
||||
|
||||
// We may be required to grow the vectors
|
||||
this.dimension = index + 1;
|
||||
this.tails.grow(this.dimension);
|
||||
this.lengths.grow(this.dimension);
|
||||
|
||||
this.tails.resize(this.dimension);
|
||||
this.lengths.resize(this.dimension);
|
||||
|
||||
this.lengths.array[index] = 1;
|
||||
}
|
||||
|
||||
// Appending to the list
|
||||
else {
|
||||
this.pointers[pointer] = this.tails.array[index];
|
||||
this.lengths.array[index]++;
|
||||
}
|
||||
|
||||
this.tails.array[index] = pointer;
|
||||
this.items[pointer] = item;
|
||||
}
|
||||
else {
|
||||
|
||||
// This linked list does not exist yet. Let's create it
|
||||
if (index >= this.dimension) {
|
||||
|
||||
// We may be required to grow the vectors
|
||||
this.dimension = index + 1;
|
||||
this.tails.grow(this.dimension);
|
||||
this.lengths.grow(this.dimension);
|
||||
|
||||
this.tails.resize(this.dimension);
|
||||
this.lengths.resize(this.dimension);
|
||||
|
||||
this.pointers.push(0);
|
||||
this.lengths.array[index] = 1;
|
||||
}
|
||||
|
||||
// Appending to the list
|
||||
else {
|
||||
this.pointers.push(this.tails.array[index]);
|
||||
this.lengths.array[index]++;
|
||||
}
|
||||
|
||||
this.tails.array[index] = pointer;
|
||||
this.items.push(item);
|
||||
}
|
||||
|
||||
this.size++;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to push a new container holding the given value.
|
||||
* Note: it might be useful to make this function able to take an iterable
|
||||
* or variadic someday. For the time being it's just a convenience for
|
||||
* implementing compact multi maps and such.
|
||||
*
|
||||
* @param {any} item - Item to add.
|
||||
* @return {MultiArray}
|
||||
*/
|
||||
MultiArray.prototype.push = function(item) {
|
||||
var pointer = this.size,
|
||||
index = this.dimension;
|
||||
|
||||
if (this.hasFixedCapacity) {
|
||||
|
||||
if (index >= this.capacity || this.size === this.capacity)
|
||||
throw new Error('mnemonist/multi-array: attempting to allocate further than capacity.');
|
||||
|
||||
this.items[pointer] = item;
|
||||
}
|
||||
else {
|
||||
this.items.push(item);
|
||||
this.pointers.push(0);
|
||||
}
|
||||
|
||||
this.lengths.push(1);
|
||||
this.tails.push(pointer);
|
||||
|
||||
this.dimension++;
|
||||
this.size++;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the desired container.
|
||||
*
|
||||
* @param {number} index - Index of the container.
|
||||
* @return {array}
|
||||
*/
|
||||
MultiArray.prototype.get = function(index) {
|
||||
if (index >= this.dimension)
|
||||
return;
|
||||
|
||||
var pointers = this.hasFixedCapacity ? this.pointers : this.pointers.array;
|
||||
|
||||
var pointer = this.tails.array[index],
|
||||
length = this.lengths.array[index],
|
||||
i = length;
|
||||
|
||||
var array = new this.Container(length);
|
||||
|
||||
while (i !== 0) {
|
||||
array[--i] = this.items[pointer];
|
||||
pointer = pointers[pointer];
|
||||
}
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to check if a container exists at the given index.
|
||||
*
|
||||
* @param {number} index - Index of the container.
|
||||
* @return {boolean}
|
||||
*/
|
||||
MultiArray.prototype.has = function(index) {
|
||||
return index < this.dimension;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the size of the container stored at given index.
|
||||
*
|
||||
* @param {number} index - Index of the container.
|
||||
* @return {number}
|
||||
*/
|
||||
MultiArray.prototype.multiplicity = function(index) {
|
||||
if (index >= this.dimension)
|
||||
return 0;
|
||||
|
||||
return this.lengths.array[index];
|
||||
};
|
||||
MultiArray.prototype.count = MultiArray.prototype.multiplicity;
|
||||
|
||||
/**
|
||||
* Method used to iterate over the structure's containers.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
MultiArray.prototype.containers = function() {
|
||||
var self = this,
|
||||
l = this.dimension,
|
||||
i = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= l)
|
||||
return {done: true};
|
||||
|
||||
return {value: self.get(i++)};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the structure's associations.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
MultiArray.prototype.associations = function() {
|
||||
var self = this,
|
||||
l = this.dimension,
|
||||
i = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= l)
|
||||
return {done: true};
|
||||
|
||||
var data = {value: [i, self.get(i)]};
|
||||
|
||||
i++;
|
||||
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the structure's values in the global insertion
|
||||
* order.
|
||||
*
|
||||
* @param {number} [index] - Optionally, iterate over the values of a single
|
||||
* container at index.
|
||||
* @return {Iterator}
|
||||
*/
|
||||
MultiArray.prototype.values = function(index) {
|
||||
var items = this.items,
|
||||
length,
|
||||
i = 0;
|
||||
|
||||
if (typeof index === 'number') {
|
||||
if (index >= this.dimension)
|
||||
return Iterator.empty();
|
||||
|
||||
length = this.lengths.array[index];
|
||||
items = this.items;
|
||||
|
||||
var pointers = this.hasFixedCapacity ? this.pointers : this.pointers.array;
|
||||
|
||||
if (length === 0)
|
||||
return Iterator.empty();
|
||||
|
||||
var pointer = this.tails.array[index],
|
||||
v;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i === length)
|
||||
return {done: true};
|
||||
|
||||
i++;
|
||||
v = items[pointer];
|
||||
pointer = pointers[pointer];
|
||||
|
||||
return {done: false, value: v};
|
||||
});
|
||||
}
|
||||
|
||||
length = this.size;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= length)
|
||||
return {done: true};
|
||||
|
||||
return {done: false, value: items[i++]};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the structure's entries.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
MultiArray.prototype.entries = function() {
|
||||
if (this.size === 0)
|
||||
return Iterator.empty();
|
||||
|
||||
var inContainer = false,
|
||||
pointer,
|
||||
length,
|
||||
i = 0,
|
||||
j = 0,
|
||||
l = this.dimension,
|
||||
v;
|
||||
|
||||
var pointers = this.hasFixedCapacity ? this.pointers : this.pointers.array,
|
||||
items = this.items,
|
||||
tails = this.tails.array,
|
||||
lengths = this.lengths.array;
|
||||
|
||||
var iterator = new Iterator(function next() {
|
||||
if (!inContainer) {
|
||||
|
||||
if (i >= l)
|
||||
return {done: true};
|
||||
|
||||
length = lengths[i];
|
||||
pointer = tails[i];
|
||||
i++;
|
||||
|
||||
if (length === 0)
|
||||
return next();
|
||||
|
||||
j = 0;
|
||||
inContainer = true;
|
||||
}
|
||||
|
||||
if (j === length) {
|
||||
inContainer = false;
|
||||
return next();
|
||||
}
|
||||
|
||||
v = items[pointer];
|
||||
|
||||
// TODO: guard for out-of-bounds
|
||||
pointer = pointers[pointer];
|
||||
|
||||
j++;
|
||||
|
||||
return {
|
||||
done: false,
|
||||
value: [i - 1, v]
|
||||
};
|
||||
});
|
||||
|
||||
return iterator;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the structure's keys.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
MultiArray.prototype.keys = function() {
|
||||
var i = 0,
|
||||
l = this.dimension;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= l)
|
||||
return {done: true};
|
||||
|
||||
return {done: false, value: i++};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
MultiArray.prototype.inspect = function() {
|
||||
var proxy = new Array(this.dimension),
|
||||
i,
|
||||
l;
|
||||
|
||||
for (i = 0, l = this.dimension; i < l; i++)
|
||||
proxy[i] = Array.from(this.get(i));
|
||||
|
||||
if (this.hasFixedCapacity) {
|
||||
proxy.type = this.Container.name;
|
||||
proxy.capacity = this.capacity;
|
||||
}
|
||||
|
||||
proxy.size = this.size;
|
||||
proxy.dimension = this.dimension;
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: MultiArray,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
MultiArray.prototype[Symbol.for('nodejs.util.inspect.custom')] = MultiArray.prototype.inspect;
|
||||
|
||||
// TODO: .from
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = MultiArray;
|
||||
47
backend/node_modules/mnemonist/multi-map.d.ts
generated
vendored
Normal file
47
backend/node_modules/mnemonist/multi-map.d.ts
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Mnemonist MultiMap Typings
|
||||
* ===========================
|
||||
*/
|
||||
|
||||
interface MultiMap<K, V, C extends V[] | Set<V> = V[]> extends Iterable<[K, V]> {
|
||||
|
||||
// Members
|
||||
dimension: number;
|
||||
size: number;
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
set(key: K, value: V): this;
|
||||
delete(key: K): boolean;
|
||||
remove(key: K, value: V): boolean;
|
||||
has(key: K): boolean;
|
||||
get(key: K): C | undefined;
|
||||
multiplicity(key: K): number;
|
||||
forEach(callback: (value: V, key: K, map: this) => void, scope?: any): void;
|
||||
forEachAssociation(callback: (value: C, key: K, map: this) => void, scope?: any): void;
|
||||
keys(): IterableIterator<K>;
|
||||
values(): IterableIterator<V>;
|
||||
entries(): IterableIterator<[K, V]>;
|
||||
containers(): IterableIterator<C>;
|
||||
associations(): IterableIterator<[K, C]>;
|
||||
[Symbol.iterator](): IterableIterator<[K, V]>;
|
||||
inspect(): any;
|
||||
toJSON(): any;
|
||||
}
|
||||
|
||||
interface MultiMapConstructor {
|
||||
new <K, V>(container: SetConstructor): MultiMap<K, V, Set<V>>;
|
||||
new <K, V>(container?: ArrayConstructor): MultiMap<K, V, V[]>;
|
||||
|
||||
from<K, V>(
|
||||
iterable: Iterable<[K, V]> | {[key: string]: V},
|
||||
Container: SetConstructor
|
||||
): MultiMap<K, V, Set<V>>;
|
||||
from<K, V>(
|
||||
iterable: Iterable<[K, V]> | {[key: string]: V},
|
||||
Container?: ArrayConstructor
|
||||
): MultiMap<K, V, V[]>;
|
||||
}
|
||||
|
||||
declare const MultiMap: MultiMapConstructor;
|
||||
export default MultiMap;
|
||||
408
backend/node_modules/mnemonist/multi-map.js
generated
vendored
Normal file
408
backend/node_modules/mnemonist/multi-map.js
generated
vendored
Normal file
@@ -0,0 +1,408 @@
|
||||
/**
|
||||
* Mnemonist MultiMap
|
||||
* ===================
|
||||
*
|
||||
* Implementation of a MultiMap with custom container.
|
||||
*/
|
||||
var Iterator = require('obliterator/iterator'),
|
||||
forEach = require('obliterator/foreach');
|
||||
|
||||
/**
|
||||
* MultiMap.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function MultiMap(Container) {
|
||||
|
||||
this.Container = Container || Array;
|
||||
this.items = new Map();
|
||||
this.clear();
|
||||
|
||||
Object.defineProperty(this.items, 'constructor', {
|
||||
value: MultiMap,
|
||||
enumerable: false
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
MultiMap.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
this.dimension = 0;
|
||||
this.items.clear();
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set a value.
|
||||
*
|
||||
* @param {any} key - Key.
|
||||
* @param {any} value - Value to add.
|
||||
* @return {MultiMap}
|
||||
*/
|
||||
MultiMap.prototype.set = function(key, value) {
|
||||
var container = this.items.get(key),
|
||||
sizeBefore;
|
||||
|
||||
if (!container) {
|
||||
this.dimension++;
|
||||
container = new this.Container();
|
||||
this.items.set(key, container);
|
||||
}
|
||||
|
||||
if (this.Container === Set) {
|
||||
sizeBefore = container.size;
|
||||
container.add(value);
|
||||
|
||||
if (sizeBefore < container.size)
|
||||
this.size++;
|
||||
}
|
||||
else {
|
||||
container.push(value);
|
||||
this.size++;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to delete the given key.
|
||||
*
|
||||
* @param {any} key - Key to delete.
|
||||
* @return {boolean}
|
||||
*/
|
||||
MultiMap.prototype.delete = function(key) {
|
||||
var container = this.items.get(key);
|
||||
|
||||
if (!container)
|
||||
return false;
|
||||
|
||||
this.size -= (this.Container === Set ? container.size : container.length);
|
||||
this.dimension--;
|
||||
this.items.delete(key);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to delete the remove an item in the container stored at the
|
||||
* given key.
|
||||
*
|
||||
* @param {any} key - Key to delete.
|
||||
* @return {boolean}
|
||||
*/
|
||||
MultiMap.prototype.remove = function(key, value) {
|
||||
var container = this.items.get(key),
|
||||
wasDeleted,
|
||||
index;
|
||||
|
||||
if (!container)
|
||||
return false;
|
||||
|
||||
if (this.Container === Set) {
|
||||
wasDeleted = container.delete(value);
|
||||
|
||||
if (wasDeleted)
|
||||
this.size--;
|
||||
|
||||
if (container.size === 0) {
|
||||
this.items.delete(key);
|
||||
this.dimension--;
|
||||
}
|
||||
|
||||
return wasDeleted;
|
||||
}
|
||||
else {
|
||||
index = container.indexOf(value);
|
||||
|
||||
if (index === -1)
|
||||
return false;
|
||||
|
||||
this.size--;
|
||||
|
||||
if (container.length === 1) {
|
||||
this.items.delete(key);
|
||||
this.dimension--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
container.splice(index, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to return whether the given keys exists in the map.
|
||||
*
|
||||
* @param {any} key - Key to check.
|
||||
* @return {boolean}
|
||||
*/
|
||||
MultiMap.prototype.has = function(key) {
|
||||
return this.items.has(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to return the container stored at the given key or `undefined`.
|
||||
*
|
||||
* @param {any} key - Key to get.
|
||||
* @return {boolean}
|
||||
*/
|
||||
MultiMap.prototype.get = function(key) {
|
||||
return this.items.get(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to return the multiplicity of the given key, meaning the number
|
||||
* of times it is set, or, more trivially, the size of the attached container.
|
||||
*
|
||||
* @param {any} key - Key to check.
|
||||
* @return {number}
|
||||
*/
|
||||
MultiMap.prototype.multiplicity = function(key) {
|
||||
var container = this.items.get(key);
|
||||
|
||||
if (typeof container === 'undefined')
|
||||
return 0;
|
||||
|
||||
return this.Container === Set ? container.size : container.length;
|
||||
};
|
||||
MultiMap.prototype.count = MultiMap.prototype.multiplicity;
|
||||
|
||||
/**
|
||||
* Method used to iterate over each of the key/value pairs.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
MultiMap.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
// Inner iteration function is created here to avoid creating it in the loop
|
||||
var key;
|
||||
function inner(value) {
|
||||
callback.call(scope, value, key);
|
||||
}
|
||||
|
||||
this.items.forEach(function(container, k) {
|
||||
key = k;
|
||||
container.forEach(inner);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over each of the associations.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
MultiMap.prototype.forEachAssociation = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
this.items.forEach(callback, scope);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the map's keys.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
MultiMap.prototype.keys = function() {
|
||||
return this.items.keys();
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the map's keys.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
MultiMap.prototype.values = function() {
|
||||
var iterator = this.items.values(),
|
||||
inContainer = false,
|
||||
countainer,
|
||||
step,
|
||||
i,
|
||||
l;
|
||||
|
||||
if (this.Container === Set)
|
||||
return new Iterator(function next() {
|
||||
if (!inContainer) {
|
||||
step = iterator.next();
|
||||
|
||||
if (step.done)
|
||||
return {done: true};
|
||||
|
||||
inContainer = true;
|
||||
countainer = step.value.values();
|
||||
}
|
||||
|
||||
step = countainer.next();
|
||||
|
||||
if (step.done) {
|
||||
inContainer = false;
|
||||
return next();
|
||||
}
|
||||
|
||||
return {
|
||||
done: false,
|
||||
value: step.value
|
||||
};
|
||||
});
|
||||
|
||||
return new Iterator(function next() {
|
||||
if (!inContainer) {
|
||||
step = iterator.next();
|
||||
|
||||
if (step.done)
|
||||
return {done: true};
|
||||
|
||||
inContainer = true;
|
||||
countainer = step.value;
|
||||
i = 0;
|
||||
l = countainer.length;
|
||||
}
|
||||
|
||||
if (i >= l) {
|
||||
inContainer = false;
|
||||
return next();
|
||||
}
|
||||
|
||||
return {
|
||||
done: false,
|
||||
value: countainer[i++]
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the map's entries.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
MultiMap.prototype.entries = function() {
|
||||
var iterator = this.items.entries(),
|
||||
inContainer = false,
|
||||
countainer,
|
||||
step,
|
||||
key,
|
||||
i,
|
||||
l;
|
||||
|
||||
if (this.Container === Set)
|
||||
return new Iterator(function next() {
|
||||
if (!inContainer) {
|
||||
step = iterator.next();
|
||||
|
||||
if (step.done)
|
||||
return {done: true};
|
||||
|
||||
inContainer = true;
|
||||
key = step.value[0];
|
||||
countainer = step.value[1].values();
|
||||
}
|
||||
|
||||
step = countainer.next();
|
||||
|
||||
if (step.done) {
|
||||
inContainer = false;
|
||||
return next();
|
||||
}
|
||||
|
||||
return {
|
||||
done: false,
|
||||
value: [key, step.value]
|
||||
};
|
||||
});
|
||||
|
||||
return new Iterator(function next() {
|
||||
if (!inContainer) {
|
||||
step = iterator.next();
|
||||
|
||||
if (step.done)
|
||||
return {done: true};
|
||||
|
||||
inContainer = true;
|
||||
key = step.value[0];
|
||||
countainer = step.value[1];
|
||||
i = 0;
|
||||
l = countainer.length;
|
||||
}
|
||||
|
||||
if (i >= l) {
|
||||
inContainer = false;
|
||||
return next();
|
||||
}
|
||||
|
||||
return {
|
||||
done: false,
|
||||
value: [key, countainer[i++]]
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the map's containers.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
MultiMap.prototype.containers = function() {
|
||||
return this.items.values();
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the map's associations.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
MultiMap.prototype.associations = function() {
|
||||
return this.items.entries();
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.entries method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
MultiMap.prototype[Symbol.iterator] = MultiMap.prototype.entries;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
MultiMap.prototype.inspect = function() {
|
||||
return this.items;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
MultiMap.prototype[Symbol.for('nodejs.util.inspect.custom')] = MultiMap.prototype.inspect;
|
||||
MultiMap.prototype.toJSON = function() {
|
||||
return this.items;
|
||||
};
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a structure.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {Class} Container - Container.
|
||||
* @return {MultiMap}
|
||||
*/
|
||||
MultiMap.from = function(iterable, Container) {
|
||||
var map = new MultiMap(Container);
|
||||
|
||||
forEach(iterable, function(value, key) {
|
||||
map.set(key, value);
|
||||
});
|
||||
|
||||
return map;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = MultiMap;
|
||||
37
backend/node_modules/mnemonist/multi-set.d.ts
generated
vendored
Normal file
37
backend/node_modules/mnemonist/multi-set.d.ts
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Mnemonist MultiSet Typings
|
||||
* ===========================
|
||||
*/
|
||||
export default class MultiSet<K> implements Iterable<K> {
|
||||
|
||||
// Members
|
||||
dimension: number;
|
||||
size: number;
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
add(key: K, count?: number): this;
|
||||
set(key: K, count: number): this;
|
||||
has(key: K): boolean;
|
||||
delete(key: K): boolean;
|
||||
remove(key: K, count?: number): void;
|
||||
edit(a: K, b: K): this;
|
||||
multiplicity(key: K): number;
|
||||
count(key: K): number;
|
||||
get(key: K): number;
|
||||
frequency(key: K): number;
|
||||
top(n: number): Array<[K, number]>;
|
||||
forEach(callback: (value: K, key: K, set: this) => void, scope?: any): void;
|
||||
forEachMultiplicity(callback: (value: number, key: K, set: this) => void, scope?: any): void;
|
||||
keys(): IterableIterator<K>;
|
||||
values(): IterableIterator<K>;
|
||||
multiplicities(): IterableIterator<[K, number]>;
|
||||
[Symbol.iterator](): IterableIterator<K>;
|
||||
inspect(): any;
|
||||
toJSON(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(iterable: Iterable<I> | {[key: string]: I}): MultiSet<I>;
|
||||
static isSubset<T>(a: MultiSet<T>, b: MultiSet<T>): boolean;
|
||||
static isSuperset<T>(a: MultiSet<T>, b: MultiSet<T>): boolean;
|
||||
}
|
||||
445
backend/node_modules/mnemonist/multi-set.js
generated
vendored
Normal file
445
backend/node_modules/mnemonist/multi-set.js
generated
vendored
Normal file
@@ -0,0 +1,445 @@
|
||||
/**
|
||||
* Mnemonist MultiSet
|
||||
* ====================
|
||||
*
|
||||
* JavaScript implementation of a MultiSet.
|
||||
*/
|
||||
var Iterator = require('obliterator/iterator'),
|
||||
forEach = require('obliterator/foreach'),
|
||||
FixedReverseHeap = require('./fixed-reverse-heap.js');
|
||||
|
||||
/**
|
||||
* Helpers.
|
||||
*/
|
||||
var MULTISET_ITEM_COMPARATOR = function(a, b) {
|
||||
if (a[1] > b[1])
|
||||
return -1;
|
||||
if (a[1] < b[1])
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
// TODO: helper functions: union, intersection, sum, difference, subtract
|
||||
|
||||
/**
|
||||
* MultiSet.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function MultiSet() {
|
||||
this.items = new Map();
|
||||
|
||||
Object.defineProperty(this.items, 'constructor', {
|
||||
value: MultiSet,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
MultiSet.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
this.dimension = 0;
|
||||
this.items.clear();
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add an item to the set.
|
||||
*
|
||||
* @param {any} item - Item to add.
|
||||
* @param {number} count - Optional count.
|
||||
* @return {MultiSet}
|
||||
*/
|
||||
MultiSet.prototype.add = function(item, count) {
|
||||
if (count === 0)
|
||||
return this;
|
||||
|
||||
if (count < 0)
|
||||
return this.remove(item, -count);
|
||||
|
||||
count = count || 1;
|
||||
|
||||
if (typeof count !== 'number')
|
||||
throw new Error('mnemonist/multi-set.add: given count should be a number.');
|
||||
|
||||
this.size += count;
|
||||
|
||||
const currentCount = this.items.get(item);
|
||||
|
||||
if (currentCount === undefined)
|
||||
this.dimension++;
|
||||
else
|
||||
count += currentCount;
|
||||
|
||||
this.items.set(item, count);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set the multiplicity of an item in the set.
|
||||
*
|
||||
* @param {any} item - Target item.
|
||||
* @param {number} count - Desired multiplicity.
|
||||
* @return {MultiSet}
|
||||
*/
|
||||
MultiSet.prototype.set = function(item, count) {
|
||||
var currentCount;
|
||||
|
||||
if (typeof count !== 'number')
|
||||
throw new Error('mnemonist/multi-set.set: given count should be a number.');
|
||||
|
||||
// Setting an item to 0 or to a negative number means deleting it from the set
|
||||
if (count <= 0) {
|
||||
currentCount = this.items.get(item);
|
||||
|
||||
if (typeof currentCount !== 'undefined') {
|
||||
this.size -= currentCount;
|
||||
this.dimension--;
|
||||
}
|
||||
|
||||
this.items.delete(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
count = count || 1;
|
||||
|
||||
currentCount = this.items.get(item);
|
||||
|
||||
if (typeof currentCount === 'number') {
|
||||
this.items.set(item, currentCount + count);
|
||||
}
|
||||
else {
|
||||
this.dimension++;
|
||||
this.items.set(item, count);
|
||||
}
|
||||
|
||||
this.size += count;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to return whether the item exists in the set.
|
||||
*
|
||||
* @param {any} item - Item to check.
|
||||
* @return {boolan}
|
||||
*/
|
||||
MultiSet.prototype.has = function(item) {
|
||||
return this.items.has(item);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to delete an item from the set.
|
||||
*
|
||||
* @param {any} item - Item to delete.
|
||||
* @return {boolan}
|
||||
*/
|
||||
MultiSet.prototype.delete = function(item) {
|
||||
var count = this.items.get(item);
|
||||
|
||||
if (count === 0)
|
||||
return false;
|
||||
|
||||
this.size -= count;
|
||||
this.dimension--;
|
||||
this.items.delete(item);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to remove an item from the set.
|
||||
*
|
||||
* @param {any} item - Item to delete.
|
||||
* @param {number} count - Optional count.
|
||||
* @return {undefined}
|
||||
*/
|
||||
MultiSet.prototype.remove = function(item, count) {
|
||||
if (count === 0)
|
||||
return;
|
||||
|
||||
if (count < 0)
|
||||
return this.add(item, -count);
|
||||
|
||||
count = count || 1;
|
||||
|
||||
if (typeof count !== 'number')
|
||||
throw new Error('mnemonist/multi-set.remove: given count should be a number.');
|
||||
|
||||
var currentCount = this.items.get(item);
|
||||
|
||||
if (typeof currentCount === 'undefined') return;
|
||||
|
||||
var newCount = Math.max(0, currentCount - count);
|
||||
|
||||
if (newCount === 0) {
|
||||
this.items.delete(item);
|
||||
this.size -= currentCount;
|
||||
this.dimension--;
|
||||
}
|
||||
else {
|
||||
this.items.set(item, newCount);
|
||||
this.size -= count;
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to change a key into another one, merging counts if the target
|
||||
* key already exists.
|
||||
*
|
||||
* @param {any} a - From key.
|
||||
* @param {any} b - To key.
|
||||
* @return {MultiSet}
|
||||
*/
|
||||
MultiSet.prototype.edit = function(a, b) {
|
||||
var am = this.multiplicity(a);
|
||||
|
||||
// If a does not exist in the set, we can stop right there
|
||||
if (am === 0)
|
||||
return;
|
||||
|
||||
var bm = this.multiplicity(b);
|
||||
|
||||
this.items.set(b, am + bm);
|
||||
this.items.delete(a);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to return the multiplicity of the given item.
|
||||
*
|
||||
* @param {any} item - Item to get.
|
||||
* @return {number}
|
||||
*/
|
||||
MultiSet.prototype.multiplicity = function(item) {
|
||||
var count = this.items.get(item);
|
||||
|
||||
if (typeof count === 'undefined')
|
||||
return 0;
|
||||
|
||||
return count;
|
||||
};
|
||||
MultiSet.prototype.get = MultiSet.prototype.multiplicity;
|
||||
MultiSet.prototype.count = MultiSet.prototype.multiplicity;
|
||||
|
||||
/**
|
||||
* Method used to return the frequency of the given item in the set.
|
||||
*
|
||||
* @param {any} item - Item to get.
|
||||
* @return {number}
|
||||
*/
|
||||
MultiSet.prototype.frequency = function(item) {
|
||||
if (this.size === 0)
|
||||
return 0;
|
||||
|
||||
var count = this.multiplicity(item);
|
||||
|
||||
return count / this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to return the n most common items from the set.
|
||||
*
|
||||
* @param {number} n - Number of items to retrieve.
|
||||
* @return {array}
|
||||
*/
|
||||
MultiSet.prototype.top = function(n) {
|
||||
if (typeof n !== 'number' || n <= 0)
|
||||
throw new Error('mnemonist/multi-set.top: n must be a number > 0.');
|
||||
|
||||
var heap = new FixedReverseHeap(Array, MULTISET_ITEM_COMPARATOR, n);
|
||||
|
||||
var iterator = this.items.entries(),
|
||||
step;
|
||||
|
||||
while ((step = iterator.next(), !step.done))
|
||||
heap.push(step.value);
|
||||
|
||||
return heap.consume();
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the set's values.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
MultiSet.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
var i;
|
||||
|
||||
this.items.forEach(function(multiplicity, value) {
|
||||
|
||||
for (i = 0; i < multiplicity; i++)
|
||||
callback.call(scope, value, value);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the set's multiplicities.
|
||||
*
|
||||
* @param {function} callback - Function to call for each multiplicity.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
MultiSet.prototype.forEachMultiplicity = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
this.items.forEach(callback, scope);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the set's keys. I.e. its unique values,
|
||||
* in a sense.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
MultiSet.prototype.keys = function() {
|
||||
return this.items.keys();
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the set's values.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
MultiSet.prototype.values = function() {
|
||||
var iterator = this.items.entries(),
|
||||
inContainer = false,
|
||||
step,
|
||||
value,
|
||||
multiplicity,
|
||||
i;
|
||||
|
||||
return new Iterator(function next() {
|
||||
if (!inContainer) {
|
||||
step = iterator.next();
|
||||
|
||||
if (step.done)
|
||||
return {done: true};
|
||||
|
||||
inContainer = true;
|
||||
value = step.value[0];
|
||||
multiplicity = step.value[1];
|
||||
i = 0;
|
||||
}
|
||||
|
||||
if (i >= multiplicity) {
|
||||
inContainer = false;
|
||||
return next();
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
return {
|
||||
done: false,
|
||||
value: value
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the set's multiplicities.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
MultiSet.prototype.multiplicities = function() {
|
||||
return this.items.entries();
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.entries method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
MultiSet.prototype[Symbol.iterator] = MultiSet.prototype.values;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
MultiSet.prototype.inspect = function() {
|
||||
return this.items;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
MultiSet.prototype[Symbol.for('nodejs.util.inspect.custom')] = MultiSet.prototype.inspect;
|
||||
MultiSet.prototype.toJSON = function() {
|
||||
return this.items;
|
||||
};
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a structure.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @return {MultiSet}
|
||||
*/
|
||||
MultiSet.from = function(iterable) {
|
||||
var set = new MultiSet();
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
set.add(value);
|
||||
});
|
||||
|
||||
return set;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function returning whether the multiset A is a subset of the multiset B.
|
||||
*
|
||||
* @param {MultiSet} A - First set.
|
||||
* @param {MultiSet} B - Second set.
|
||||
* @return {boolean}
|
||||
*/
|
||||
MultiSet.isSubset = function(A, B) {
|
||||
var iterator = A.multiplicities(),
|
||||
step,
|
||||
key,
|
||||
mA;
|
||||
|
||||
// Shortcuts
|
||||
if (A === B)
|
||||
return true;
|
||||
|
||||
if (A.dimension > B.dimension)
|
||||
return false;
|
||||
|
||||
while ((step = iterator.next(), !step.done)) {
|
||||
key = step.value[0];
|
||||
mA = step.value[1];
|
||||
|
||||
if (B.multiplicity(key) < mA)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function returning whether the multiset A is a superset of the multiset B.
|
||||
*
|
||||
* @param {MultiSet} A - First set.
|
||||
* @param {MultiSet} B - Second set.
|
||||
* @return {boolean}
|
||||
*/
|
||||
MultiSet.isSuperset = function(A, B) {
|
||||
return MultiSet.isSubset(B, A);
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = MultiSet;
|
||||
104
backend/node_modules/mnemonist/package.json
generated
vendored
Normal file
104
backend/node_modules/mnemonist/package.json
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"name": "mnemonist",
|
||||
"version": "0.39.6",
|
||||
"description": "Curated collection of data structures for the JavaScript/TypeScript.",
|
||||
"scripts": {
|
||||
"lint": "eslint --cache ./*.js ./utils ./test",
|
||||
"lint:fix": "eslint --cache --fix ./*.js ./utils ./test",
|
||||
"prepublishOnly": "npm run lint && npm test && npm run test:types",
|
||||
"test": "mocha",
|
||||
"test:types": "tsc --target es2015 --noEmit --noImplicitAny --noImplicitReturns ./test/types.ts"
|
||||
},
|
||||
"main": "./index.js",
|
||||
"types": "./index.d.ts",
|
||||
"files": [
|
||||
"sort",
|
||||
"utils",
|
||||
"*.d.ts",
|
||||
"*.js"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/yomguithereal/mnemonist.git"
|
||||
},
|
||||
"keywords": [
|
||||
"bag",
|
||||
"bimap",
|
||||
"bit array",
|
||||
"bit set",
|
||||
"bit vector",
|
||||
"bitset",
|
||||
"bk tree",
|
||||
"burkhard-keller tree",
|
||||
"cache",
|
||||
"circular buffer",
|
||||
"counter",
|
||||
"data structures",
|
||||
"default map",
|
||||
"deque",
|
||||
"disjoint set",
|
||||
"fibonacci heap",
|
||||
"fuzzy map",
|
||||
"hashed array tree",
|
||||
"heap",
|
||||
"interval tree",
|
||||
"inverted index",
|
||||
"kd tree",
|
||||
"linked list",
|
||||
"lru",
|
||||
"lru cache",
|
||||
"multimap",
|
||||
"multiset",
|
||||
"passjoin",
|
||||
"queue",
|
||||
"sparse map",
|
||||
"sparse set",
|
||||
"stack",
|
||||
"structures",
|
||||
"suffix tree",
|
||||
"symspell",
|
||||
"trie",
|
||||
"union find",
|
||||
"vantage point tree",
|
||||
"vector",
|
||||
"vp tree"
|
||||
],
|
||||
"author": {
|
||||
"name": "Guillaume Plique",
|
||||
"url": "http://github.com/Yomguithereal"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/yomguithereal/mnemonist/issues"
|
||||
},
|
||||
"homepage": "https://github.com/yomguithereal/mnemonist#readme",
|
||||
"dependencies": {
|
||||
"obliterator": "^2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@yomguithereal/eslint-config": "^4.4.0",
|
||||
"asciitree": "^1.0.2",
|
||||
"damerau-levenshtein": "^1.0.7",
|
||||
"eslint": "^8.2.0",
|
||||
"leven": "^3.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"matcha": "^0.7.0",
|
||||
"mocha": "^9.1.3",
|
||||
"pandemonium": "^2.0.0",
|
||||
"seedrandom": "^3.0.5",
|
||||
"static-kdtree": "^1.0.2",
|
||||
"typescript": "^4.5.2"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "@yomguithereal/eslint-config",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"ecmaFeatures": {
|
||||
"forOf": true
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"no-new": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
54
backend/node_modules/mnemonist/passjoin-index.d.ts
generated
vendored
Normal file
54
backend/node_modules/mnemonist/passjoin-index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Mnemonist PassjoinIndex Typings
|
||||
* ================================
|
||||
*/
|
||||
type LevenshteinDistanceFunction<T> = (a: T, b: T) => number;
|
||||
|
||||
export default class PassjoinIndex<T> implements Iterable<T> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(levenshtein: LevenshteinDistanceFunction<T>, k: number);
|
||||
|
||||
// Methods
|
||||
add(value: T): this;
|
||||
search(query: T): Set<T>;
|
||||
clear(): void;
|
||||
forEach(callback: (value: T, index: number, self: this) => void, scope?: any): void;
|
||||
values(): IterableIterator<T>;
|
||||
[Symbol.iterator](): IterableIterator<T>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(
|
||||
iterable: Iterable<I> | {[key: string]: I},
|
||||
levenshtein: LevenshteinDistanceFunction<I>,
|
||||
k: number
|
||||
): PassjoinIndex<I>;
|
||||
}
|
||||
|
||||
export function countKeys(k: number, s: number): number;
|
||||
export function comparator<T>(a: T, b: T): number;
|
||||
export function partition(k: number, l: number): Array<[number, number]>;
|
||||
export function segments<T>(k: number, string: T): Array<T>;
|
||||
export function segmentPos<T>(k: number, i: number, string: T): number;
|
||||
|
||||
export function multiMatchAwareInterval(
|
||||
k: number,
|
||||
delta: number,
|
||||
i: number,
|
||||
s: number,
|
||||
pi: number,
|
||||
li: number
|
||||
): [number, number];
|
||||
|
||||
export function multiMatchAwareSubstrings<T>(
|
||||
k: number,
|
||||
string: T,
|
||||
l: number,
|
||||
i: number,
|
||||
pi: number,
|
||||
li: number
|
||||
): Array<T>;
|
||||
518
backend/node_modules/mnemonist/passjoin-index.js
generated
vendored
Normal file
518
backend/node_modules/mnemonist/passjoin-index.js
generated
vendored
Normal file
@@ -0,0 +1,518 @@
|
||||
/**
|
||||
* Mnemonist PassjoinIndex
|
||||
* ========================
|
||||
*
|
||||
* The PassjoinIndex is an index leveraging the "passjoin" algorithm as a mean
|
||||
* to index strings for Levenshtein distance queries. It features a complexity
|
||||
* related to the Levenshtein query threshold k rather than the number of
|
||||
* strings to test (roughly O(k^3)).
|
||||
*
|
||||
* [References]:
|
||||
* Jiang, Yu, Dong Deng, Jiannan Wang, Guoliang Li, et Jianhua Feng.
|
||||
* « Efficient Parallel Partition-Based Algorithms for Similarity Search and Join
|
||||
* with Edit Distance Constraints ». In Proceedings of the Joint EDBT/ICDT 2013
|
||||
* Workshops on - EDBT ’13, 341. Genoa, Italy: ACM Press, 2013.
|
||||
* https://doi.org/10.1145/2457317.2457382.
|
||||
*
|
||||
* Li, Guoliang, Dong Deng, et Jianhua Feng. « A Partition-Based Method for
|
||||
* String Similarity Joins with Edit-Distance Constraints ». ACM Transactions on
|
||||
* Database Systems 38, no 2 (1 juin 2013): 1‑33.
|
||||
* https://doi.org/10.1145/2487259.2487261.
|
||||
*
|
||||
* [Urls]:
|
||||
* http://people.csail.mit.edu/dongdeng/projects/passjoin/index.html
|
||||
*/
|
||||
var Iterator = require('obliterator/iterator'),
|
||||
forEach = require('obliterator/foreach');
|
||||
|
||||
// TODO: leveraging BagDistance as an upper bound of Levenshtein
|
||||
// TODO: leverage n-grams recursive indexing
|
||||
// TODO: try the MultiArray as a memory backend
|
||||
// TODO: what about damerau levenshtein
|
||||
|
||||
/**
|
||||
* Helpers.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Function returning the number of substrings that will be selected by the
|
||||
* multi-match-aware selection scheme for theshold `k`, for a string of length
|
||||
* `s` to match strings of length `l`.
|
||||
*
|
||||
* @param {number} k - Levenshtein distance threshold.
|
||||
* @param {number} s - Length of target strings.
|
||||
* @param {number} l - Length of strings to match.
|
||||
* @returns {number} - The number of selected substrings.
|
||||
*/
|
||||
function countSubstringsL(k, s, l) {
|
||||
return (((Math.pow(k, 2) - Math.pow(Math.abs(s - l), 2)) / 2) | 0) + k + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function returning the minimum number of substrings that will be selected by
|
||||
* the multi-match-aware selection scheme for theshold `k`, for a string of
|
||||
* length `s` to match any string of relevant length.
|
||||
*
|
||||
* @param {number} k - Levenshtein distance threshold.
|
||||
* @param {number} s - Length of target strings.
|
||||
* @returns {number} - The number of selected substrings.
|
||||
*/
|
||||
function countKeys(k, s) {
|
||||
var c = 0;
|
||||
|
||||
for (var l = 0, m = s + 1; l < m; l++)
|
||||
c += countSubstringsL(k, s, l);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to compare two keys in order to sort them first by decreasing
|
||||
* length and then alphabetically as per the "4.2 Effective Indexing Strategy"
|
||||
* point of the paper.
|
||||
*
|
||||
* @param {number} k - Levenshtein distance threshold.
|
||||
* @param {number} s - Length of target strings.
|
||||
* @returns {number} - The number of selected substrings.
|
||||
*/
|
||||
function comparator(a, b) {
|
||||
if (a.length > b.length)
|
||||
return -1;
|
||||
if (a.length < b.length)
|
||||
return 1;
|
||||
|
||||
if (a < b)
|
||||
return -1;
|
||||
if (a > b)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function partitioning a string into k + 1 uneven segments, the shorter
|
||||
* ones, then the longer ones.
|
||||
*
|
||||
* @param {number} k - Levenshtein distance threshold.
|
||||
* @param {number} l - Length of the string.
|
||||
* @returns {Array} - The partition tuples (start, length).
|
||||
*/
|
||||
function partition(k, l) {
|
||||
var m = k + 1,
|
||||
a = (l / m) | 0,
|
||||
b = a + 1,
|
||||
i,
|
||||
j;
|
||||
|
||||
var largeSegments = l - a * m,
|
||||
smallSegments = m - largeSegments;
|
||||
|
||||
var tuples = new Array(k + 1);
|
||||
|
||||
for (i = 0; i < smallSegments; i++)
|
||||
tuples[i] = [i * a, a];
|
||||
|
||||
var offset = (i - 1) * a + a;
|
||||
|
||||
for (j = 0; j < largeSegments; j++)
|
||||
tuples[i + j] = [offset + j * b, b];
|
||||
|
||||
return tuples;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function yielding a string's k + 1 passjoin segments to index.
|
||||
*
|
||||
* @param {number} k - Levenshtein distance threshold.
|
||||
* @param {string} string - Target string.
|
||||
* @returns {Array} - The string's segments.
|
||||
*/
|
||||
function segments(k, string) {
|
||||
var l = string.length,
|
||||
m = k + 1,
|
||||
a = (l / m) | 0,
|
||||
b = a + 1,
|
||||
o,
|
||||
i,
|
||||
j;
|
||||
|
||||
var largeSegments = l - a * m,
|
||||
smallSegments = m - largeSegments;
|
||||
|
||||
var S = new Array(k + 1);
|
||||
|
||||
for (i = 0; i < smallSegments; i++) {
|
||||
o = i * a;
|
||||
S[i] = string.slice(o, o + a);
|
||||
}
|
||||
|
||||
var offset = (i - 1) * a + a;
|
||||
|
||||
for (j = 0; j < largeSegments; j++) {
|
||||
o = offset + j * b;
|
||||
S[i + j] = string.slice(o, o + b);
|
||||
}
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
// TODO: jsdocs
|
||||
function segmentPos(k, i, string) {
|
||||
if (i === 0)
|
||||
return 0;
|
||||
|
||||
var l = string.length;
|
||||
|
||||
var m = k + 1,
|
||||
a = (l / m) | 0,
|
||||
b = a + 1;
|
||||
|
||||
var largeSegments = l - a * m,
|
||||
smallSegments = m - largeSegments;
|
||||
|
||||
if (i <= smallSegments - 1)
|
||||
return i * a;
|
||||
|
||||
var offset = i - smallSegments;
|
||||
|
||||
return smallSegments * a + offset * b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function returning the interval of relevant substrings to lookup using the
|
||||
* multi-match-aware substring selection scheme described in the paper.
|
||||
*
|
||||
* @param {number} k - Levenshtein distance threshold.
|
||||
* @param {number} delta - Signed length difference between both considered strings.
|
||||
* @param {number} i - k + 1 segment index.
|
||||
* @param {number} s - String's length.
|
||||
* @param {number} pi - k + 1 segment position in target string.
|
||||
* @param {number} li - k + 1 segment length.
|
||||
* @returns {Array} - The interval (start, stop).
|
||||
*/
|
||||
function multiMatchAwareInterval(k, delta, i, s, pi, li) {
|
||||
var start1 = pi - i,
|
||||
end1 = pi + i;
|
||||
|
||||
var o = k - i;
|
||||
|
||||
var start2 = pi + delta - o,
|
||||
end2 = pi + delta + o;
|
||||
|
||||
var end3 = s - li;
|
||||
|
||||
return [Math.max(0, start1, start2), Math.min(end1, end2, end3)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Function yielding relevant substrings to lookup using the multi-match-aware
|
||||
* substring selection scheme described in the paper.
|
||||
*
|
||||
* @param {number} k - Levenshtein distance threshold.
|
||||
* @param {string} string - Target string.
|
||||
* @param {number} l - Length of strings to match.
|
||||
* @param {number} i - k + 1 segment index.
|
||||
* @param {number} pi - k + 1 segment position in target string.
|
||||
* @param {number} li - k + 1 segment length.
|
||||
* @returns {Array} - The contiguous substrings.
|
||||
*/
|
||||
function multiMatchAwareSubstrings(k, string, l, i, pi, li) {
|
||||
var s = string.length;
|
||||
|
||||
// Note that we need to keep the non-absolute delta for this function
|
||||
// to work in both directions, up & down
|
||||
var delta = s - l;
|
||||
|
||||
var interval = multiMatchAwareInterval(k, delta, i, s, pi, li);
|
||||
|
||||
var start = interval[0],
|
||||
stop = interval[1];
|
||||
|
||||
var currentSubstring = '';
|
||||
|
||||
var substrings = [];
|
||||
|
||||
var substring, j, m;
|
||||
|
||||
for (j = start, m = stop + 1; j < m; j++) {
|
||||
substring = string.slice(j, j + li);
|
||||
|
||||
// We skip identical consecutive substrings (to avoid repetition in case
|
||||
// of contiguous letter duplication)
|
||||
if (substring === currentSubstring)
|
||||
continue;
|
||||
|
||||
substrings.push(substring);
|
||||
|
||||
currentSubstring = substring;
|
||||
}
|
||||
|
||||
return substrings;
|
||||
}
|
||||
|
||||
/**
|
||||
* PassjoinIndex.
|
||||
*
|
||||
* @note I tried to apply the paper's optimizations regarding Levenshtein
|
||||
* distance computations but it did not provide a performance boost, quite
|
||||
* the contrary. This is because since we are mostly using the index for small k
|
||||
* here, most of the strings we work on are quite small and the bookkeeping
|
||||
* induced by Ukkonen's method and the paper's one are slowing us down more than
|
||||
* they actually help us go faster.
|
||||
*
|
||||
* @note This implementation does not try to ensure that you add the same string
|
||||
* more than once.
|
||||
*
|
||||
* @constructor
|
||||
* @param {function} levenshtein - Levenshtein distance function.
|
||||
* @param {number} k - Levenshtein distance threshold.
|
||||
*/
|
||||
function PassjoinIndex(levenshtein, k) {
|
||||
if (typeof levenshtein !== 'function')
|
||||
throw new Error('mnemonist/passjoin-index: `levenshtein` should be a function returning edit distance between two strings.');
|
||||
|
||||
if (typeof k !== 'number' || k < 1)
|
||||
throw new Error('mnemonist/passjoin-index: `k` should be a number > 0');
|
||||
|
||||
this.levenshtein = levenshtein;
|
||||
this.k = k;
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
PassjoinIndex.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
this.strings = [];
|
||||
this.invertedIndices = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add a new value to the index.
|
||||
*
|
||||
* @param {string|Array} value - Value to add.
|
||||
* @return {PassjoinIndex}
|
||||
*/
|
||||
PassjoinIndex.prototype.add = function(value) {
|
||||
var l = value.length;
|
||||
|
||||
var stringIndex = this.size;
|
||||
|
||||
this.strings.push(value);
|
||||
this.size++;
|
||||
|
||||
var S = segments(this.k, value);
|
||||
|
||||
var Ll = this.invertedIndices[l];
|
||||
|
||||
if (typeof Ll === 'undefined') {
|
||||
Ll = {};
|
||||
this.invertedIndices[l] = Ll;
|
||||
}
|
||||
|
||||
var segment,
|
||||
matches,
|
||||
key,
|
||||
i,
|
||||
m;
|
||||
|
||||
for (i = 0, m = S.length; i < m; i++) {
|
||||
segment = S[i];
|
||||
key = segment + i;
|
||||
matches = Ll[key];
|
||||
|
||||
if (typeof matches === 'undefined') {
|
||||
matches = [stringIndex];
|
||||
Ll[key] = matches;
|
||||
}
|
||||
else {
|
||||
matches.push(stringIndex);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to search for string matching the given query.
|
||||
*
|
||||
* @param {string|Array} query - Query string.
|
||||
* @return {Array}
|
||||
*/
|
||||
PassjoinIndex.prototype.search = function(query) {
|
||||
var s = query.length,
|
||||
k = this.k;
|
||||
|
||||
var M = new Set();
|
||||
|
||||
var candidates,
|
||||
candidate,
|
||||
queryPos,
|
||||
querySegmentLength,
|
||||
key,
|
||||
S,
|
||||
P,
|
||||
l,
|
||||
m,
|
||||
i,
|
||||
n1,
|
||||
j,
|
||||
n2,
|
||||
y,
|
||||
n3;
|
||||
|
||||
for (l = Math.max(0, s - k), m = s + k + 1; l < m; l++) {
|
||||
var Ll = this.invertedIndices[l];
|
||||
|
||||
if (typeof Ll === 'undefined')
|
||||
continue;
|
||||
|
||||
P = partition(k, l);
|
||||
|
||||
for (i = 0, n1 = P.length; i < n1; i++) {
|
||||
queryPos = P[i][0];
|
||||
querySegmentLength = P[i][1];
|
||||
|
||||
S = multiMatchAwareSubstrings(
|
||||
k,
|
||||
query,
|
||||
l,
|
||||
i,
|
||||
queryPos,
|
||||
querySegmentLength
|
||||
);
|
||||
|
||||
// Empty string edge case
|
||||
if (!S.length)
|
||||
S = [''];
|
||||
|
||||
for (j = 0, n2 = S.length; j < n2; j++) {
|
||||
key = S[j] + i;
|
||||
candidates = Ll[key];
|
||||
|
||||
if (typeof candidates === 'undefined')
|
||||
continue;
|
||||
|
||||
for (y = 0, n3 = candidates.length; y < n3; y++) {
|
||||
candidate = this.strings[candidates[y]];
|
||||
|
||||
// NOTE: first condition is here not to compute Levenshtein
|
||||
// distance for tiny strings
|
||||
|
||||
// NOTE: maintaining a Set of rejected candidate is not really useful
|
||||
// because it consumes more memory and because non-matches are
|
||||
// less likely to be candidates agains
|
||||
if (
|
||||
s <= k && l <= k ||
|
||||
(
|
||||
!M.has(candidate) &&
|
||||
this.levenshtein(query, candidate) <= k
|
||||
)
|
||||
)
|
||||
M.add(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return M;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the index.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
PassjoinIndex.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
for (var i = 0, l = this.strings.length; i < l; i++)
|
||||
callback.call(scope, this.strings[i], i, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a index's values.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
PassjoinIndex.prototype.values = function() {
|
||||
var strings = this.strings,
|
||||
l = strings.length,
|
||||
i = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= l)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
var value = strings[i];
|
||||
i++;
|
||||
|
||||
return {
|
||||
value: value,
|
||||
done: false
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.values method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
PassjoinIndex.prototype[Symbol.iterator] = PassjoinIndex.prototype.values;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
PassjoinIndex.prototype.inspect = function() {
|
||||
var array = this.strings.slice();
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(array, 'constructor', {
|
||||
value: PassjoinIndex,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
PassjoinIndex.prototype[Symbol.for('nodejs.util.inspect.custom')] = PassjoinIndex.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a structure.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @return {PassjoinIndex}
|
||||
*/
|
||||
PassjoinIndex.from = function(iterable, levenshtein, k) {
|
||||
var index = new PassjoinIndex(levenshtein, k);
|
||||
|
||||
forEach(iterable, function(string) {
|
||||
index.add(string);
|
||||
});
|
||||
|
||||
return index;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
PassjoinIndex.countKeys = countKeys;
|
||||
PassjoinIndex.comparator = comparator;
|
||||
PassjoinIndex.partition = partition;
|
||||
PassjoinIndex.segments = segments;
|
||||
PassjoinIndex.segmentPos = segmentPos;
|
||||
PassjoinIndex.multiMatchAwareInterval = multiMatchAwareInterval;
|
||||
PassjoinIndex.multiMatchAwareSubstrings = multiMatchAwareSubstrings;
|
||||
|
||||
module.exports = PassjoinIndex;
|
||||
27
backend/node_modules/mnemonist/queue.d.ts
generated
vendored
Normal file
27
backend/node_modules/mnemonist/queue.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Mnemonist Queue Typings
|
||||
* ========================
|
||||
*/
|
||||
export default class Queue<T> implements Iterable<T> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
enqueue(item: T): number;
|
||||
dequeue(): T | undefined;
|
||||
peek(): T | undefined;
|
||||
forEach(callback: (item: T, index: number, queue: this) => void, scope?: any): void;
|
||||
toArray(): Array<T>;
|
||||
values(): IterableIterator<T>;
|
||||
entries(): IterableIterator<[number, T]>;
|
||||
[Symbol.iterator](): IterableIterator<T>;
|
||||
toString(): string;
|
||||
toJSON(): Array<T>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(iterable: Iterable<I> | {[key: string]: I}): Queue<I>;
|
||||
static of<I>(...items: Array<I>): Queue<I>;
|
||||
}
|
||||
215
backend/node_modules/mnemonist/queue.js
generated
vendored
Normal file
215
backend/node_modules/mnemonist/queue.js
generated
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
/**
|
||||
* Mnemonist Queue
|
||||
* ================
|
||||
*
|
||||
* Queue implementation based on the ideas of Queue.js that seems to beat
|
||||
* a LinkedList one in performance.
|
||||
*/
|
||||
var Iterator = require('obliterator/iterator'),
|
||||
forEach = require('obliterator/foreach');
|
||||
|
||||
/**
|
||||
* Queue
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function Queue() {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the queue.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
Queue.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.items = [];
|
||||
this.offset = 0;
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add an item to the queue.
|
||||
*
|
||||
* @param {any} item - Item to enqueue.
|
||||
* @return {number}
|
||||
*/
|
||||
Queue.prototype.enqueue = function(item) {
|
||||
|
||||
this.items.push(item);
|
||||
return ++this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to retrieve & remove the first item of the queue.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
Queue.prototype.dequeue = function() {
|
||||
if (!this.size)
|
||||
return;
|
||||
|
||||
var item = this.items[this.offset];
|
||||
|
||||
if (++this.offset * 2 >= this.items.length) {
|
||||
this.items = this.items.slice(this.offset);
|
||||
this.offset = 0;
|
||||
}
|
||||
|
||||
this.size--;
|
||||
|
||||
return item;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to retrieve the first item of the queue.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
Queue.prototype.peek = function() {
|
||||
if (!this.size)
|
||||
return;
|
||||
|
||||
return this.items[this.offset];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the queue.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
Queue.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
for (var i = this.offset, j = 0, l = this.items.length; i < l; i++, j++)
|
||||
callback.call(scope, this.items[i], j, this);
|
||||
};
|
||||
|
||||
/*
|
||||
* Method used to convert the queue to a JavaScript array.
|
||||
*
|
||||
* @return {array}
|
||||
*/
|
||||
Queue.prototype.toArray = function() {
|
||||
return this.items.slice(this.offset);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a queue's values.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
Queue.prototype.values = function() {
|
||||
var items = this.items,
|
||||
i = this.offset;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= items.length)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
var value = items[i];
|
||||
i++;
|
||||
|
||||
return {
|
||||
value: value,
|
||||
done: false
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a queue's entries.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
Queue.prototype.entries = function() {
|
||||
var items = this.items,
|
||||
i = this.offset,
|
||||
j = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= items.length)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
var value = items[i];
|
||||
i++;
|
||||
|
||||
return {
|
||||
value: [j++, value],
|
||||
done: false
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.values method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
Queue.prototype[Symbol.iterator] = Queue.prototype.values;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
Queue.prototype.toString = function() {
|
||||
return this.toArray().join(',');
|
||||
};
|
||||
|
||||
Queue.prototype.toJSON = function() {
|
||||
return this.toArray();
|
||||
};
|
||||
|
||||
Queue.prototype.inspect = function() {
|
||||
var array = this.toArray();
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(array, 'constructor', {
|
||||
value: Queue,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
Queue.prototype[Symbol.for('nodejs.util.inspect.custom')] = Queue.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a queue.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @return {Queue}
|
||||
*/
|
||||
Queue.from = function(iterable) {
|
||||
var queue = new Queue();
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
queue.enqueue(value);
|
||||
});
|
||||
|
||||
return queue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Static @.of function taking an arbitrary number of arguments & converting it
|
||||
* into a queue.
|
||||
*
|
||||
* @param {...any} args
|
||||
* @return {Queue}
|
||||
*/
|
||||
Queue.of = function() {
|
||||
return Queue.from(arguments);
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = Queue;
|
||||
251
backend/node_modules/mnemonist/semi-dynamic-trie.js
generated
vendored
Normal file
251
backend/node_modules/mnemonist/semi-dynamic-trie.js
generated
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
/* eslint no-constant-condition: 0 */
|
||||
/**
|
||||
* Mnemonist SemiDynamicTrie
|
||||
* ==========================
|
||||
*
|
||||
* Lowlevel Trie working at character level, storing information in typed
|
||||
* array and organizing its children in linked lists.
|
||||
*
|
||||
* This implementation also uses a "fat node" strategy to boost access to some
|
||||
* bloated node's children when the number of children rises above a certain
|
||||
* threshold.
|
||||
*/
|
||||
var Vector = require('./vector.js');
|
||||
|
||||
// TODO: rename => ternary search tree
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
*/
|
||||
const MAX_LINKED = 7;
|
||||
|
||||
/**
|
||||
* SemiDynamicTrie.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function SemiDynamicTrie() {
|
||||
|
||||
// Properties
|
||||
|
||||
// TODO: make it 16 bits
|
||||
this.characters = new Vector.Uint8Vector(256);
|
||||
this.nextPointers = new Vector.Int32Vector(256);
|
||||
this.childPointers = new Vector.Uint32Vector(256);
|
||||
this.maps = new Vector.Uint32Vector(256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
SemiDynamicTrie.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
};
|
||||
|
||||
SemiDynamicTrie.prototype.ensureSibling = function(block, character) {
|
||||
var nextCharacter,
|
||||
nextBlock,
|
||||
newBlock;
|
||||
|
||||
// Do we have a root?
|
||||
if (this.characters.length === 0) {
|
||||
|
||||
this.nextPointers.push(0);
|
||||
this.childPointers.push(0);
|
||||
this.characters.push(character);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
// Are we traversing a fat node?
|
||||
var fatNode = this.nextPointers.array[block];
|
||||
|
||||
if (fatNode < 0) {
|
||||
var mapIndex = -fatNode + character;
|
||||
|
||||
nextBlock = this.maps.array[mapIndex];
|
||||
|
||||
if (nextBlock !== 0)
|
||||
return nextBlock;
|
||||
|
||||
newBlock = this.characters.length;
|
||||
|
||||
this.nextPointers.push(0);
|
||||
this.childPointers.push(0);
|
||||
this.characters.push(character);
|
||||
|
||||
this.maps.set(mapIndex, newBlock);
|
||||
|
||||
return newBlock;
|
||||
}
|
||||
|
||||
var listLength = 1,
|
||||
startingBlock = block;
|
||||
|
||||
while (true) {
|
||||
nextCharacter = this.characters.array[block];
|
||||
|
||||
if (nextCharacter === character)
|
||||
return block;
|
||||
|
||||
nextBlock = this.nextPointers.array[block];
|
||||
|
||||
if (nextBlock === 0)
|
||||
break;
|
||||
|
||||
listLength++;
|
||||
block = nextBlock;
|
||||
}
|
||||
|
||||
// If the list is too long, we create a fat node
|
||||
if (listLength > MAX_LINKED) {
|
||||
block = startingBlock;
|
||||
|
||||
var offset = this.maps.length;
|
||||
|
||||
this.maps.resize(offset + 255);
|
||||
this.maps.set(offset + 255, 0);
|
||||
|
||||
while (true) {
|
||||
nextBlock = this.nextPointers.array[block];
|
||||
|
||||
if (nextBlock === 0)
|
||||
break;
|
||||
|
||||
nextCharacter = this.characters.array[nextBlock];
|
||||
this.maps.set(offset + nextCharacter, nextBlock);
|
||||
|
||||
block = nextBlock;
|
||||
}
|
||||
|
||||
this.nextPointers.set(startingBlock, -offset);
|
||||
|
||||
newBlock = this.characters.length;
|
||||
|
||||
this.nextPointers.push(0);
|
||||
this.childPointers.push(0);
|
||||
this.characters.push(character);
|
||||
|
||||
this.maps.set(offset + character, newBlock);
|
||||
|
||||
return newBlock;
|
||||
}
|
||||
|
||||
// Else, we append the character to the list
|
||||
newBlock = this.characters.length;
|
||||
|
||||
this.nextPointers.push(0);
|
||||
this.childPointers.push(0);
|
||||
this.nextPointers.set(block, newBlock);
|
||||
this.characters.push(character);
|
||||
|
||||
return newBlock;
|
||||
};
|
||||
|
||||
SemiDynamicTrie.prototype.findSibling = function(block, character) {
|
||||
var nextCharacter;
|
||||
|
||||
// Do we have a fat node?
|
||||
var fatNode = this.nextPointers.array[block];
|
||||
|
||||
if (fatNode < 0) {
|
||||
var mapIndex = -fatNode + character;
|
||||
|
||||
var nextBlock = this.maps.array[mapIndex];
|
||||
|
||||
if (nextBlock === 0)
|
||||
return -1;
|
||||
|
||||
return nextBlock;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
nextCharacter = this.characters.array[block];
|
||||
|
||||
if (nextCharacter === character)
|
||||
return block;
|
||||
|
||||
block = this.nextPointers.array[block];
|
||||
|
||||
if (block === 0)
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
SemiDynamicTrie.prototype.add = function(key) {
|
||||
var keyCharacter,
|
||||
childBlock,
|
||||
block = 0;
|
||||
|
||||
var i = 0, l = key.length;
|
||||
|
||||
// Going as far as possible
|
||||
while (i < l) {
|
||||
keyCharacter = key.charCodeAt(i);
|
||||
|
||||
// Ensuring a correct sibling exists
|
||||
block = this.ensureSibling(block, keyCharacter);
|
||||
|
||||
i++;
|
||||
|
||||
if (i < l) {
|
||||
|
||||
// Descending
|
||||
childBlock = this.childPointers.array[block];
|
||||
|
||||
if (childBlock === 0)
|
||||
break;
|
||||
|
||||
block = childBlock;
|
||||
}
|
||||
}
|
||||
|
||||
// Adding as many blocks as necessary
|
||||
while (i < l) {
|
||||
|
||||
childBlock = this.characters.length;
|
||||
this.characters.push(key.charCodeAt(i));
|
||||
|
||||
this.childPointers.push(0);
|
||||
this.nextPointers.push(0);
|
||||
this.childPointers.set(block, childBlock);
|
||||
|
||||
block = childBlock;
|
||||
|
||||
i++;
|
||||
}
|
||||
};
|
||||
|
||||
SemiDynamicTrie.prototype.has = function(key) {
|
||||
var i, l;
|
||||
|
||||
var block = 0,
|
||||
siblingBlock;
|
||||
|
||||
for (i = 0, l = key.length; i < l; i++) {
|
||||
siblingBlock = this.findSibling(block, key.charCodeAt(i));
|
||||
|
||||
if (siblingBlock === -1)
|
||||
return false;
|
||||
|
||||
// TODO: be sure
|
||||
if (i === l - 1)
|
||||
return true;
|
||||
|
||||
block = this.childPointers.array[siblingBlock];
|
||||
|
||||
if (block === 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: fix, should have a leaf pointer somehow
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = SemiDynamicTrie;
|
||||
18
backend/node_modules/mnemonist/set.d.ts
generated
vendored
Normal file
18
backend/node_modules/mnemonist/set.d.ts
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Mnemonist Set Typings
|
||||
* ======================
|
||||
*/
|
||||
export function intersection<T>(...set: Array<Set<T>>): Set<T>;
|
||||
export function union<T>(...set: Array<Set<T>>): Set<T>;
|
||||
export function difference<T>(a: Set<T>, b: Set<T>): Set<T>;
|
||||
export function symmetricDifference<T>(a: Set<T>, b: Set<T>): Set<T>;
|
||||
export function isSubset<T>(a: Set<T>, b: Set<T>): boolean;
|
||||
export function isSuperset<T>(a: Set<T>, b: Set<T>): boolean;
|
||||
export function add<T>(a: Set<T>, b: Set<T>): void;
|
||||
export function subtract<T>(a: Set<T>, b: Set<T>): void;
|
||||
export function intersect<T>(a: Set<T>, b: Set<T>): void;
|
||||
export function disjunct<T>(a: Set<T>, b: Set<T>): void;
|
||||
export function intersectionSize<T>(a: Set<T>, b: Set<T>): number;
|
||||
export function unionSize<T>(a: Set<T>, b: Set<T>): number;
|
||||
export function jaccard<T>(a: Set<T>, b: Set<T>): number;
|
||||
export function overlap<T>(a: Set<T>, b: Set<T>): number;
|
||||
356
backend/node_modules/mnemonist/set.js
generated
vendored
Normal file
356
backend/node_modules/mnemonist/set.js
generated
vendored
Normal file
@@ -0,0 +1,356 @@
|
||||
/**
|
||||
* Mnemonist Set
|
||||
* ==============
|
||||
*
|
||||
* Useful function related to sets such as union, intersection and so on...
|
||||
*/
|
||||
|
||||
// TODO: optimize versions for less variadicities
|
||||
|
||||
/**
|
||||
* Variadic function computing the intersection of multiple sets.
|
||||
*
|
||||
* @param {...Set} sets - Sets to intersect.
|
||||
* @return {Set} - The intesection.
|
||||
*/
|
||||
exports.intersection = function() {
|
||||
if (arguments.length < 2)
|
||||
throw new Error('mnemonist/Set.intersection: needs at least two arguments.');
|
||||
|
||||
var I = new Set();
|
||||
|
||||
// First we need to find the smallest set
|
||||
var smallestSize = Infinity,
|
||||
smallestSet = null;
|
||||
|
||||
var s, i, l = arguments.length;
|
||||
|
||||
for (i = 0; i < l; i++) {
|
||||
s = arguments[i];
|
||||
|
||||
// If one of the set has no items, we can stop right there
|
||||
if (s.size === 0)
|
||||
return I;
|
||||
|
||||
if (s.size < smallestSize) {
|
||||
smallestSize = s.size;
|
||||
smallestSet = s;
|
||||
}
|
||||
}
|
||||
|
||||
// Now we need to intersect this set with the others
|
||||
var iterator = smallestSet.values(),
|
||||
step,
|
||||
item,
|
||||
add,
|
||||
set;
|
||||
|
||||
// TODO: we can optimize by iterating each next time over the current intersection
|
||||
// but this probably means more RAM to consume since we'll create n-1 sets rather than
|
||||
// only the one.
|
||||
while ((step = iterator.next(), !step.done)) {
|
||||
item = step.value;
|
||||
add = true;
|
||||
|
||||
for (i = 0; i < l; i++) {
|
||||
set = arguments[i];
|
||||
|
||||
if (set === smallestSet)
|
||||
continue;
|
||||
|
||||
if (!set.has(item)) {
|
||||
add = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (add)
|
||||
I.add(item);
|
||||
}
|
||||
|
||||
return I;
|
||||
};
|
||||
|
||||
/**
|
||||
* Variadic function computing the union of multiple sets.
|
||||
*
|
||||
* @param {...Set} sets - Sets to unite.
|
||||
* @return {Set} - The union.
|
||||
*/
|
||||
exports.union = function() {
|
||||
if (arguments.length < 2)
|
||||
throw new Error('mnemonist/Set.union: needs at least two arguments.');
|
||||
|
||||
var U = new Set();
|
||||
|
||||
var i, l = arguments.length;
|
||||
|
||||
var iterator,
|
||||
step;
|
||||
|
||||
for (i = 0; i < l; i++) {
|
||||
iterator = arguments[i].values();
|
||||
|
||||
while ((step = iterator.next(), !step.done))
|
||||
U.add(step.value);
|
||||
}
|
||||
|
||||
return U;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function computing the difference between two sets.
|
||||
*
|
||||
* @param {Set} A - First set.
|
||||
* @param {Set} B - Second set.
|
||||
* @return {Set} - The difference.
|
||||
*/
|
||||
exports.difference = function(A, B) {
|
||||
|
||||
// If first set is empty
|
||||
if (!A.size)
|
||||
return new Set();
|
||||
|
||||
if (!B.size)
|
||||
return new Set(A);
|
||||
|
||||
var D = new Set();
|
||||
|
||||
var iterator = A.values(),
|
||||
step;
|
||||
|
||||
while ((step = iterator.next(), !step.done)) {
|
||||
if (!B.has(step.value))
|
||||
D.add(step.value);
|
||||
}
|
||||
|
||||
return D;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function computing the symmetric difference between two sets.
|
||||
*
|
||||
* @param {Set} A - First set.
|
||||
* @param {Set} B - Second set.
|
||||
* @return {Set} - The symmetric difference.
|
||||
*/
|
||||
exports.symmetricDifference = function(A, B) {
|
||||
var S = new Set();
|
||||
|
||||
var iterator = A.values(),
|
||||
step;
|
||||
|
||||
while ((step = iterator.next(), !step.done)) {
|
||||
if (!B.has(step.value))
|
||||
S.add(step.value);
|
||||
}
|
||||
|
||||
iterator = B.values();
|
||||
|
||||
while ((step = iterator.next(), !step.done)) {
|
||||
if (!A.has(step.value))
|
||||
S.add(step.value);
|
||||
}
|
||||
|
||||
return S;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function returning whether A is a subset of B.
|
||||
*
|
||||
* @param {Set} A - First set.
|
||||
* @param {Set} B - Second set.
|
||||
* @return {boolean}
|
||||
*/
|
||||
exports.isSubset = function(A, B) {
|
||||
var iterator = A.values(),
|
||||
step;
|
||||
|
||||
// Shortcuts
|
||||
if (A === B)
|
||||
return true;
|
||||
|
||||
if (A.size > B.size)
|
||||
return false;
|
||||
|
||||
while ((step = iterator.next(), !step.done)) {
|
||||
if (!B.has(step.value))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function returning whether A is a superset of B.
|
||||
*
|
||||
* @param {Set} A - First set.
|
||||
* @param {Set} B - Second set.
|
||||
* @return {boolean}
|
||||
*/
|
||||
exports.isSuperset = function(A, B) {
|
||||
return exports.isSubset(B, A);
|
||||
};
|
||||
|
||||
/**
|
||||
* Function adding the items of set B to the set A.
|
||||
*
|
||||
* @param {Set} A - First set.
|
||||
* @param {Set} B - Second set.
|
||||
*/
|
||||
exports.add = function(A, B) {
|
||||
var iterator = B.values(),
|
||||
step;
|
||||
|
||||
while ((step = iterator.next(), !step.done))
|
||||
A.add(step.value);
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function subtracting the items of set B from the set A.
|
||||
*
|
||||
* @param {Set} A - First set.
|
||||
* @param {Set} B - Second set.
|
||||
*/
|
||||
exports.subtract = function(A, B) {
|
||||
var iterator = B.values(),
|
||||
step;
|
||||
|
||||
while ((step = iterator.next(), !step.done))
|
||||
A.delete(step.value);
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function intersecting the items of A & B.
|
||||
*
|
||||
* @param {Set} A - First set.
|
||||
* @param {Set} B - Second set.
|
||||
*/
|
||||
exports.intersect = function(A, B) {
|
||||
var iterator = A.values(),
|
||||
step;
|
||||
|
||||
while ((step = iterator.next(), !step.done)) {
|
||||
if (!B.has(step.value))
|
||||
A.delete(step.value);
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function disjuncting the items of A & B.
|
||||
*
|
||||
* @param {Set} A - First set.
|
||||
* @param {Set} B - Second set.
|
||||
*/
|
||||
exports.disjunct = function(A, B) {
|
||||
var iterator = A.values(),
|
||||
step;
|
||||
|
||||
var toRemove = [];
|
||||
|
||||
while ((step = iterator.next(), !step.done)) {
|
||||
if (B.has(step.value))
|
||||
toRemove.push(step.value);
|
||||
}
|
||||
|
||||
iterator = B.values();
|
||||
|
||||
while ((step = iterator.next(), !step.done)) {
|
||||
if (!A.has(step.value))
|
||||
A.add(step.value);
|
||||
}
|
||||
|
||||
for (var i = 0, l = toRemove.length; i < l; i++)
|
||||
A.delete(toRemove[i]);
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function returning the size of the intersection of A & B.
|
||||
*
|
||||
* @param {Set} A - First set.
|
||||
* @param {Set} B - Second set.
|
||||
* @return {number}
|
||||
*/
|
||||
exports.intersectionSize = function(A, B) {
|
||||
var tmp;
|
||||
|
||||
// We need to know the smallest set
|
||||
if (A.size > B.size) {
|
||||
tmp = A;
|
||||
A = B;
|
||||
B = tmp;
|
||||
}
|
||||
|
||||
if (A.size === 0)
|
||||
return 0;
|
||||
|
||||
if (A === B)
|
||||
return A.size;
|
||||
|
||||
var iterator = A.values(),
|
||||
step;
|
||||
|
||||
var I = 0;
|
||||
|
||||
while ((step = iterator.next(), !step.done)) {
|
||||
if (B.has(step.value))
|
||||
I++;
|
||||
}
|
||||
|
||||
return I;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function returning the size of the union of A & B.
|
||||
*
|
||||
* @param {Set} A - First set.
|
||||
* @param {Set} B - Second set.
|
||||
* @return {number}
|
||||
*/
|
||||
exports.unionSize = function(A, B) {
|
||||
var I = exports.intersectionSize(A, B);
|
||||
|
||||
return A.size + B.size - I;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function returning the Jaccard similarity between A & B.
|
||||
*
|
||||
* @param {Set} A - First set.
|
||||
* @param {Set} B - Second set.
|
||||
* @return {number}
|
||||
*/
|
||||
exports.jaccard = function(A, B) {
|
||||
var I = exports.intersectionSize(A, B);
|
||||
|
||||
if (I === 0)
|
||||
return 0;
|
||||
|
||||
var U = A.size + B.size - I;
|
||||
|
||||
return I / U;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function returning the overlap coefficient between A & B.
|
||||
*
|
||||
* @param {Set} A - First set.
|
||||
* @param {Set} B - Second set.
|
||||
* @return {number}
|
||||
*/
|
||||
exports.overlap = function(A, B) {
|
||||
var I = exports.intersectionSize(A, B);
|
||||
|
||||
if (I === 0)
|
||||
return 0;
|
||||
|
||||
return I / Math.min(A.size, B.size);
|
||||
};
|
||||
4
backend/node_modules/mnemonist/sort/insertion.d.ts
generated
vendored
Normal file
4
backend/node_modules/mnemonist/sort/insertion.d.ts
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
import {IArrayLike} from '../utils/types';
|
||||
|
||||
export function inplaceInsertionSort(array: IArrayLike, lo: number, hi: number): IArrayLike;
|
||||
export function inplaceInsertionSortIndices(array: IArrayLike, indices: IArrayLike, lo: number, hi: number): IArrayLike;
|
||||
50
backend/node_modules/mnemonist/sort/insertion.js
generated
vendored
Normal file
50
backend/node_modules/mnemonist/sort/insertion.js
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Mnemonist Insertion Sort
|
||||
* =========================
|
||||
*
|
||||
* Insertion sort related functions.
|
||||
*/
|
||||
function inplaceInsertionSort(array, lo, hi) {
|
||||
i = lo + 1;
|
||||
|
||||
var j, k;
|
||||
|
||||
for (; i < hi; i++) {
|
||||
k = array[i];
|
||||
j = i - 1;
|
||||
|
||||
while (j >= lo && array[j] > k) {
|
||||
array[j + 1] = array[j];
|
||||
j--;
|
||||
}
|
||||
|
||||
array[j + 1] = k;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
exports.inplaceInsertionSort = inplaceInsertionSort;
|
||||
|
||||
function inplaceInsertionSortIndices(array, indices, lo, hi) {
|
||||
i = lo + 1;
|
||||
|
||||
var j, k, t;
|
||||
|
||||
for (; i < hi; i++) {
|
||||
t = indices[i];
|
||||
k = array[t];
|
||||
j = i - 1;
|
||||
|
||||
while (j >= lo && array[indices[j]] > k) {
|
||||
indices[j + 1] = indices[j];
|
||||
j--;
|
||||
}
|
||||
|
||||
indices[j + 1] = t;
|
||||
}
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
exports.inplaceInsertionSortIndices = inplaceInsertionSortIndices;
|
||||
4
backend/node_modules/mnemonist/sort/quick.d.ts
generated
vendored
Normal file
4
backend/node_modules/mnemonist/sort/quick.d.ts
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
import {IArrayLike} from '../utils/types';
|
||||
|
||||
export function inplaceQuickSort(array: IArrayLike, lo: number, hi: number): IArrayLike;
|
||||
export function inplaceQuickSortIndices(array: IArrayLike, indices: IArrayLike, lo: number, hi: number): IArrayLike;
|
||||
116
backend/node_modules/mnemonist/sort/quick.js
generated
vendored
Normal file
116
backend/node_modules/mnemonist/sort/quick.js
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Mnemonist Quick Sort
|
||||
* =====================
|
||||
*
|
||||
* Quick sort related functions.
|
||||
* Adapted from: https://alienryderflex.com/quicksort/
|
||||
*/
|
||||
var LOS = new Float64Array(64),
|
||||
HIS = new Float64Array(64);
|
||||
|
||||
function inplaceQuickSort(array, lo, hi) {
|
||||
var p, i, l, r, swap;
|
||||
|
||||
LOS[0] = lo;
|
||||
HIS[0] = hi;
|
||||
i = 0;
|
||||
|
||||
while (i >= 0) {
|
||||
l = LOS[i];
|
||||
r = HIS[i] - 1;
|
||||
|
||||
if (l < r) {
|
||||
p = array[l];
|
||||
|
||||
while (l < r) {
|
||||
while (array[r] >= p && l < r)
|
||||
r--;
|
||||
|
||||
if (l < r)
|
||||
array[l++] = array[r];
|
||||
|
||||
while (array[l] <= p && l < r)
|
||||
l++;
|
||||
|
||||
if (l < r)
|
||||
array[r--] = array[l];
|
||||
}
|
||||
|
||||
array[l] = p;
|
||||
LOS[i + 1] = l + 1;
|
||||
HIS[i + 1] = HIS[i];
|
||||
HIS[i++] = l;
|
||||
|
||||
if (HIS[i] - LOS[i] > HIS[i - 1] - LOS[i - 1]) {
|
||||
swap = LOS[i];
|
||||
LOS[i] = LOS[i - 1];
|
||||
LOS[i - 1] = swap;
|
||||
|
||||
swap = HIS[i];
|
||||
HIS[i] = HIS[i - 1];
|
||||
HIS[i - 1] = swap;
|
||||
}
|
||||
}
|
||||
else {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
exports.inplaceQuickSort = inplaceQuickSort;
|
||||
|
||||
function inplaceQuickSortIndices(array, indices, lo, hi) {
|
||||
var p, i, l, r, t, swap;
|
||||
|
||||
LOS[0] = lo;
|
||||
HIS[0] = hi;
|
||||
i = 0;
|
||||
|
||||
while (i >= 0) {
|
||||
l = LOS[i];
|
||||
r = HIS[i] - 1;
|
||||
|
||||
if (l < r) {
|
||||
t = indices[l];
|
||||
p = array[t];
|
||||
|
||||
while (l < r) {
|
||||
while (array[indices[r]] >= p && l < r)
|
||||
r--;
|
||||
|
||||
if (l < r)
|
||||
indices[l++] = indices[r];
|
||||
|
||||
while (array[indices[l]] <= p && l < r)
|
||||
l++;
|
||||
|
||||
if (l < r)
|
||||
indices[r--] = indices[l];
|
||||
}
|
||||
|
||||
indices[l] = t;
|
||||
LOS[i + 1] = l + 1;
|
||||
HIS[i + 1] = HIS[i];
|
||||
HIS[i++] = l;
|
||||
|
||||
if (HIS[i] - LOS[i] > HIS[i - 1] - LOS[i - 1]) {
|
||||
swap = LOS[i];
|
||||
LOS[i] = LOS[i - 1];
|
||||
LOS[i - 1] = swap;
|
||||
|
||||
swap = HIS[i];
|
||||
HIS[i] = HIS[i - 1];
|
||||
HIS[i - 1] = swap;
|
||||
}
|
||||
}
|
||||
else {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
exports.inplaceQuickSortIndices = inplaceQuickSortIndices;
|
||||
26
backend/node_modules/mnemonist/sparse-map.d.ts
generated
vendored
Normal file
26
backend/node_modules/mnemonist/sparse-map.d.ts
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Mnemonist SparseMap Typings
|
||||
* ============================
|
||||
*/
|
||||
export default class SparseMap<V> implements Iterable<[number, V]> {
|
||||
|
||||
// Members
|
||||
length: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(length: number);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
has(key: number): boolean;
|
||||
get(key: number): V | undefined;
|
||||
set(key: number, value: V): this;
|
||||
delete(key: number): boolean;
|
||||
forEach(callback: (value: V, key: number, set: this) => void, scope?: any): void;
|
||||
keys(): IterableIterator<number>;
|
||||
values(): IterableIterator<V>;
|
||||
entries(): IterableIterator<[number, V]>;
|
||||
[Symbol.iterator](): IterableIterator<[number, V]>;
|
||||
inspect(): any;
|
||||
}
|
||||
243
backend/node_modules/mnemonist/sparse-map.js
generated
vendored
Normal file
243
backend/node_modules/mnemonist/sparse-map.js
generated
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
/**
|
||||
* Mnemonist SparseMap
|
||||
* ====================
|
||||
*
|
||||
* JavaScript sparse map implemented on top of byte arrays.
|
||||
*
|
||||
* [Reference]: https://research.swtch.com/sparse
|
||||
*/
|
||||
var Iterator = require('obliterator/iterator'),
|
||||
getPointerArray = require('./utils/typed-arrays.js').getPointerArray;
|
||||
|
||||
/**
|
||||
* SparseMap.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function SparseMap(Values, length) {
|
||||
if (arguments.length < 2) {
|
||||
length = Values;
|
||||
Values = Array;
|
||||
}
|
||||
|
||||
var ByteArray = getPointerArray(length);
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
this.length = length;
|
||||
this.dense = new ByteArray(length);
|
||||
this.sparse = new ByteArray(length);
|
||||
this.vals = new Values(length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
SparseMap.prototype.clear = function() {
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to check the existence of a member in the set.
|
||||
*
|
||||
* @param {number} member - Member to test.
|
||||
* @return {SparseMap}
|
||||
*/
|
||||
SparseMap.prototype.has = function(member) {
|
||||
var index = this.sparse[member];
|
||||
|
||||
return (
|
||||
index < this.size &&
|
||||
this.dense[index] === member
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the value associated to a member in the set.
|
||||
*
|
||||
* @param {number} member - Member to test.
|
||||
* @return {any}
|
||||
*/
|
||||
SparseMap.prototype.get = function(member) {
|
||||
var index = this.sparse[member];
|
||||
|
||||
if (index < this.size && this.dense[index] === member)
|
||||
return this.vals[index];
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set a value into the map.
|
||||
*
|
||||
* @param {number} member - Member to set.
|
||||
* @param {any} value - Associated value.
|
||||
* @return {SparseMap}
|
||||
*/
|
||||
SparseMap.prototype.set = function(member, value) {
|
||||
var index = this.sparse[member];
|
||||
|
||||
if (index < this.size && this.dense[index] === member) {
|
||||
this.vals[index] = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
this.dense[this.size] = member;
|
||||
this.sparse[member] = this.size;
|
||||
this.vals[this.size] = value;
|
||||
this.size++;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to remove a member from the set.
|
||||
*
|
||||
* @param {number} member - Member to delete.
|
||||
* @return {boolean}
|
||||
*/
|
||||
SparseMap.prototype.delete = function(member) {
|
||||
var index = this.sparse[member];
|
||||
|
||||
if (index >= this.size || this.dense[index] !== member)
|
||||
return false;
|
||||
|
||||
index = this.dense[this.size - 1];
|
||||
this.dense[this.sparse[member]] = index;
|
||||
this.sparse[index] = this.sparse[member];
|
||||
this.size--;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the set's values.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
SparseMap.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
for (var i = 0; i < this.size; i++)
|
||||
callback.call(scope, this.vals[i], this.dense[i]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a set's members.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
SparseMap.prototype.keys = function() {
|
||||
var size = this.size,
|
||||
dense = this.dense,
|
||||
i = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i < size) {
|
||||
var item = dense[i];
|
||||
i++;
|
||||
|
||||
return {
|
||||
value: item
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a set's values.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
SparseMap.prototype.values = function() {
|
||||
var size = this.size,
|
||||
values = this.vals,
|
||||
i = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i < size) {
|
||||
var item = values[i];
|
||||
i++;
|
||||
|
||||
return {
|
||||
value: item
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a set's entries.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
SparseMap.prototype.entries = function() {
|
||||
var size = this.size,
|
||||
dense = this.dense,
|
||||
values = this.vals,
|
||||
i = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i < size) {
|
||||
var item = [dense[i], values[i]];
|
||||
i++;
|
||||
|
||||
return {
|
||||
value: item
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.entries method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
SparseMap.prototype[Symbol.iterator] = SparseMap.prototype.entries;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
SparseMap.prototype.inspect = function() {
|
||||
var proxy = new Map();
|
||||
|
||||
for (var i = 0; i < this.size; i++)
|
||||
proxy.set(this.dense[i], this.vals[i]);
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: SparseMap,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
proxy.length = this.length;
|
||||
|
||||
if (this.vals.constructor !== Array)
|
||||
proxy.type = this.vals.constructor.name;
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
SparseMap.prototype[Symbol.for('nodejs.util.inspect.custom')] = SparseMap.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = SparseMap;
|
||||
24
backend/node_modules/mnemonist/sparse-queue-set.d.ts
generated
vendored
Normal file
24
backend/node_modules/mnemonist/sparse-queue-set.d.ts
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Mnemonist SparseQueueSet Typings
|
||||
* =================================
|
||||
*/
|
||||
export default class SparseQueueSet implements Iterable<number> {
|
||||
|
||||
// Members
|
||||
capacity: number;
|
||||
start: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(length: number);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
has(value: number): boolean;
|
||||
enqueue(value: number): this;
|
||||
dequeue(): number | undefined;
|
||||
forEach(callback: (value: number, key: number, set: this) => void, scope?: any): void;
|
||||
values(): IterableIterator<number>;
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
inspect(): any;
|
||||
}
|
||||
218
backend/node_modules/mnemonist/sparse-queue-set.js
generated
vendored
Normal file
218
backend/node_modules/mnemonist/sparse-queue-set.js
generated
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
/**
|
||||
* Mnemonist SparseQueueSet
|
||||
* =========================
|
||||
*
|
||||
* JavaScript sparse queue set implemented on top of byte arrays.
|
||||
*
|
||||
* [Reference]: https://research.swtch.com/sparse
|
||||
*/
|
||||
var Iterator = require('obliterator/iterator'),
|
||||
getPointerArray = require('./utils/typed-arrays.js').getPointerArray;
|
||||
|
||||
/**
|
||||
* SparseQueueSet.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function SparseQueueSet(capacity) {
|
||||
|
||||
var ByteArray = getPointerArray(capacity);
|
||||
|
||||
// Properties
|
||||
this.start = 0;
|
||||
this.size = 0;
|
||||
this.capacity = capacity;
|
||||
this.dense = new ByteArray(capacity);
|
||||
this.sparse = new ByteArray(capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
SparseQueueSet.prototype.clear = function() {
|
||||
this.start = 0;
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to check the existence of a member in the queue.
|
||||
*
|
||||
* @param {number} member - Member to test.
|
||||
* @return {SparseQueueSet}
|
||||
*/
|
||||
SparseQueueSet.prototype.has = function(member) {
|
||||
if (this.size === 0)
|
||||
return false;
|
||||
|
||||
var index = this.sparse[member];
|
||||
|
||||
var inBounds = (
|
||||
index < this.capacity &&
|
||||
(
|
||||
index >= this.start &&
|
||||
index < this.start + this.size
|
||||
) ||
|
||||
(
|
||||
index < ((this.start + this.size) % this.capacity)
|
||||
)
|
||||
);
|
||||
|
||||
return (
|
||||
inBounds &&
|
||||
this.dense[index] === member
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add a member to the queue.
|
||||
*
|
||||
* @param {number} member - Member to add.
|
||||
* @return {SparseQueueSet}
|
||||
*/
|
||||
SparseQueueSet.prototype.enqueue = function(member) {
|
||||
var index = this.sparse[member];
|
||||
|
||||
if (this.size !== 0) {
|
||||
var inBounds = (
|
||||
index < this.capacity &&
|
||||
(
|
||||
index >= this.start &&
|
||||
index < this.start + this.size
|
||||
) ||
|
||||
(
|
||||
index < ((this.start + this.size) % this.capacity)
|
||||
)
|
||||
);
|
||||
|
||||
if (inBounds && this.dense[index] === member)
|
||||
return this;
|
||||
}
|
||||
|
||||
index = (this.start + this.size) % this.capacity;
|
||||
|
||||
this.dense[index] = member;
|
||||
this.sparse[member] = index;
|
||||
this.size++;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to remove the next member from the queue.
|
||||
*
|
||||
* @param {number} member - Member to delete.
|
||||
* @return {boolean}
|
||||
*/
|
||||
SparseQueueSet.prototype.dequeue = function() {
|
||||
if (this.size === 0)
|
||||
return;
|
||||
|
||||
var index = this.start;
|
||||
|
||||
this.size--;
|
||||
this.start++;
|
||||
|
||||
if (this.start === this.capacity)
|
||||
this.start = 0;
|
||||
|
||||
var member = this.dense[index];
|
||||
|
||||
this.sparse[member] = this.capacity;
|
||||
|
||||
return member;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the queue's values.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
SparseQueueSet.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
var c = this.capacity,
|
||||
l = this.size,
|
||||
i = this.start,
|
||||
j = 0;
|
||||
|
||||
while (j < l) {
|
||||
callback.call(scope, this.dense[i], j, this);
|
||||
i++;
|
||||
j++;
|
||||
|
||||
if (i === c)
|
||||
i = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a set's values.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
SparseQueueSet.prototype.values = function() {
|
||||
var dense = this.dense,
|
||||
c = this.capacity,
|
||||
l = this.size,
|
||||
i = this.start,
|
||||
j = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (j >= l)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
var value = dense[i];
|
||||
|
||||
i++;
|
||||
j++;
|
||||
|
||||
if (i === c)
|
||||
i = 0;
|
||||
|
||||
return {
|
||||
value: value,
|
||||
done: false
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.values method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
SparseQueueSet.prototype[Symbol.iterator] = SparseQueueSet.prototype.values;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
SparseQueueSet.prototype.inspect = function() {
|
||||
var proxy = [];
|
||||
|
||||
this.forEach(function(member) {
|
||||
proxy.push(member);
|
||||
});
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: SparseQueueSet,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
proxy.capacity = this.capacity;
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
SparseQueueSet.prototype[Symbol.for('nodejs.util.inspect.custom')] = SparseQueueSet.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = SparseQueueSet;
|
||||
23
backend/node_modules/mnemonist/sparse-set.d.ts
generated
vendored
Normal file
23
backend/node_modules/mnemonist/sparse-set.d.ts
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Mnemonist SparseSet Typings
|
||||
* ============================
|
||||
*/
|
||||
export default class SparseSet implements Iterable<number> {
|
||||
|
||||
// Members
|
||||
length: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(length: number);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
has(value: number): boolean;
|
||||
add(value: number): this;
|
||||
delete(value: number): boolean;
|
||||
forEach(callback: (value: number, key: number, set: this) => void, scope?: any): void;
|
||||
values(): IterableIterator<number>;
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
inspect(): any;
|
||||
}
|
||||
168
backend/node_modules/mnemonist/sparse-set.js
generated
vendored
Normal file
168
backend/node_modules/mnemonist/sparse-set.js
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* Mnemonist SparseSet
|
||||
* ====================
|
||||
*
|
||||
* JavaScript sparse set implemented on top of byte arrays.
|
||||
*
|
||||
* [Reference]: https://research.swtch.com/sparse
|
||||
*/
|
||||
var Iterator = require('obliterator/iterator'),
|
||||
getPointerArray = require('./utils/typed-arrays.js').getPointerArray;
|
||||
|
||||
/**
|
||||
* SparseSet.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function SparseSet(length) {
|
||||
|
||||
var ByteArray = getPointerArray(length);
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
this.length = length;
|
||||
this.dense = new ByteArray(length);
|
||||
this.sparse = new ByteArray(length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
SparseSet.prototype.clear = function() {
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to check the existence of a member in the set.
|
||||
*
|
||||
* @param {number} member - Member to test.
|
||||
* @return {SparseSet}
|
||||
*/
|
||||
SparseSet.prototype.has = function(member) {
|
||||
var index = this.sparse[member];
|
||||
|
||||
return (
|
||||
index < this.size &&
|
||||
this.dense[index] === member
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add a member to the set.
|
||||
*
|
||||
* @param {number} member - Member to add.
|
||||
* @return {SparseSet}
|
||||
*/
|
||||
SparseSet.prototype.add = function(member) {
|
||||
var index = this.sparse[member];
|
||||
|
||||
if (index < this.size && this.dense[index] === member)
|
||||
return this;
|
||||
|
||||
this.dense[this.size] = member;
|
||||
this.sparse[member] = this.size;
|
||||
this.size++;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to remove a member from the set.
|
||||
*
|
||||
* @param {number} member - Member to delete.
|
||||
* @return {boolean}
|
||||
*/
|
||||
SparseSet.prototype.delete = function(member) {
|
||||
var index = this.sparse[member];
|
||||
|
||||
if (index >= this.size || this.dense[index] !== member)
|
||||
return false;
|
||||
|
||||
index = this.dense[this.size - 1];
|
||||
this.dense[this.sparse[member]] = index;
|
||||
this.sparse[index] = this.sparse[member];
|
||||
this.size--;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the set's values.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
SparseSet.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
var item;
|
||||
|
||||
for (var i = 0; i < this.size; i++) {
|
||||
item = this.dense[i];
|
||||
|
||||
callback.call(scope, item, item);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a set's values.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
SparseSet.prototype.values = function() {
|
||||
var size = this.size,
|
||||
dense = this.dense,
|
||||
i = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i < size) {
|
||||
var item = dense[i];
|
||||
i++;
|
||||
|
||||
return {
|
||||
value: item
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.values method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
SparseSet.prototype[Symbol.iterator] = SparseSet.prototype.values;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
SparseSet.prototype.inspect = function() {
|
||||
var proxy = new Set();
|
||||
|
||||
for (var i = 0; i < this.size; i++)
|
||||
proxy.add(this.dense[i]);
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: SparseSet,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
proxy.length = this.length;
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
SparseSet.prototype[Symbol.for('nodejs.util.inspect.custom')] = SparseSet.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = SparseSet;
|
||||
27
backend/node_modules/mnemonist/stack.d.ts
generated
vendored
Normal file
27
backend/node_modules/mnemonist/stack.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Mnemonist Stack Typings
|
||||
* ========================
|
||||
*/
|
||||
export default class Stack<T> implements Iterable<T> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
push(item: T): number;
|
||||
pop(): T | undefined;
|
||||
peek(): T | undefined;
|
||||
forEach(callback: (item: T, index: number, stack: this) => void, scope?: any): void;
|
||||
toArray(): Array<T>;
|
||||
values(): IterableIterator<T>;
|
||||
entries(): IterableIterator<[number, T]>;
|
||||
[Symbol.iterator](): IterableIterator<T>;
|
||||
toString(): string;
|
||||
toJSON(): Array<T>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(iterable: Iterable<I> | {[key: string]: I}): Stack<I>;
|
||||
static of<I>(...items: Array<I>): Stack<I>;
|
||||
}
|
||||
210
backend/node_modules/mnemonist/stack.js
generated
vendored
Normal file
210
backend/node_modules/mnemonist/stack.js
generated
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* Mnemonist Stack
|
||||
* ================
|
||||
*
|
||||
* Stack implementation relying on JavaScript arrays, which are fast enough &
|
||||
* correctly optimized for this kind of work.
|
||||
*/
|
||||
var Iterator = require('obliterator/iterator'),
|
||||
forEach = require('obliterator/foreach');
|
||||
|
||||
/**
|
||||
* Stack
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function Stack() {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the stack.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
Stack.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.items = [];
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add an item to the stack.
|
||||
*
|
||||
* @param {any} item - Item to add.
|
||||
* @return {number}
|
||||
*/
|
||||
Stack.prototype.push = function(item) {
|
||||
this.items.push(item);
|
||||
return ++this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to retrieve & remove the last item of the stack.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
Stack.prototype.pop = function() {
|
||||
if (this.size === 0)
|
||||
return;
|
||||
|
||||
this.size--;
|
||||
return this.items.pop();
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the last item of the stack.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
Stack.prototype.peek = function() {
|
||||
return this.items[this.size - 1];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to iterate over the stack.
|
||||
*
|
||||
* @param {function} callback - Function to call for each item.
|
||||
* @param {object} scope - Optional scope.
|
||||
* @return {undefined}
|
||||
*/
|
||||
Stack.prototype.forEach = function(callback, scope) {
|
||||
scope = arguments.length > 1 ? scope : this;
|
||||
|
||||
for (var i = 0, l = this.items.length; i < l; i++)
|
||||
callback.call(scope, this.items[l - i - 1], i, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to convert the stack to a JavaScript array.
|
||||
*
|
||||
* @return {array}
|
||||
*/
|
||||
Stack.prototype.toArray = function() {
|
||||
var array = new Array(this.size),
|
||||
l = this.size - 1,
|
||||
i = this.size;
|
||||
|
||||
while (i--)
|
||||
array[i] = this.items[l - i];
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a stack's values.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
Stack.prototype.values = function() {
|
||||
var items = this.items,
|
||||
l = items.length,
|
||||
i = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= l)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
var value = items[l - i - 1];
|
||||
i++;
|
||||
|
||||
return {
|
||||
value: value,
|
||||
done: false
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to create an iterator over a stack's entries.
|
||||
*
|
||||
* @return {Iterator}
|
||||
*/
|
||||
Stack.prototype.entries = function() {
|
||||
var items = this.items,
|
||||
l = items.length,
|
||||
i = 0;
|
||||
|
||||
return new Iterator(function() {
|
||||
if (i >= l)
|
||||
return {
|
||||
done: true
|
||||
};
|
||||
|
||||
var value = items[l - i - 1];
|
||||
|
||||
return {
|
||||
value: [i++, value],
|
||||
done: false
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.values method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
Stack.prototype[Symbol.iterator] = Stack.prototype.values;
|
||||
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
Stack.prototype.toString = function() {
|
||||
return this.toArray().join(',');
|
||||
};
|
||||
|
||||
Stack.prototype.toJSON = function() {
|
||||
return this.toArray();
|
||||
};
|
||||
|
||||
Stack.prototype.inspect = function() {
|
||||
var array = this.toArray();
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(array, 'constructor', {
|
||||
value: Stack,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
Stack.prototype[Symbol.for('nodejs.util.inspect.custom')] = Stack.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a stack.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @return {Stack}
|
||||
*/
|
||||
Stack.from = function(iterable) {
|
||||
var stack = new Stack();
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
stack.push(value);
|
||||
});
|
||||
|
||||
return stack;
|
||||
};
|
||||
|
||||
/**
|
||||
* Static @.of function taking an arbitrary number of arguments & converting it
|
||||
* into a stack.
|
||||
*
|
||||
* @param {...any} args
|
||||
* @return {Stack}
|
||||
*/
|
||||
Stack.of = function() {
|
||||
return Stack.from(arguments);
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = Stack;
|
||||
23
backend/node_modules/mnemonist/static-disjoint-set.d.ts
generated
vendored
Normal file
23
backend/node_modules/mnemonist/static-disjoint-set.d.ts
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Mnemonist StaticDisjointSet Typings
|
||||
* ====================================
|
||||
*/
|
||||
import {ArrayLike} from './utils/types';
|
||||
|
||||
export default class StaticDisjointSet {
|
||||
|
||||
// Members
|
||||
dimension: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(size: number);
|
||||
|
||||
// Methods
|
||||
find(x: number): number;
|
||||
union(x: number, y: number): this;
|
||||
connected(x: number, y: number): boolean;
|
||||
mapping(): ArrayLike;
|
||||
compile(): Array<Array<number>>;
|
||||
inspect(): any;
|
||||
}
|
||||
195
backend/node_modules/mnemonist/static-disjoint-set.js
generated
vendored
Normal file
195
backend/node_modules/mnemonist/static-disjoint-set.js
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
/* eslint no-constant-condition: 0 */
|
||||
/**
|
||||
* Mnemonist StaticDisjointSet
|
||||
* ============================
|
||||
*
|
||||
* JavaScript implementation of a static disjoint set (union-find).
|
||||
*
|
||||
* Note that to remain performant, this implementation needs to know a size
|
||||
* beforehand.
|
||||
*/
|
||||
var helpers = require('./utils/typed-arrays.js');
|
||||
|
||||
/**
|
||||
* StaticDisjointSet.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function StaticDisjointSet(size) {
|
||||
|
||||
// Optimizing the typed array types
|
||||
var ParentsTypedArray = helpers.getPointerArray(size),
|
||||
RanksTypedArray = helpers.getPointerArray(Math.log2(size));
|
||||
|
||||
// Properties
|
||||
this.size = size;
|
||||
this.dimension = size;
|
||||
this.parents = new ParentsTypedArray(size);
|
||||
this.ranks = new RanksTypedArray(size);
|
||||
|
||||
// Initializing parents
|
||||
for (var i = 0; i < size; i++)
|
||||
this.parents[i] = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to find the root of the given item.
|
||||
*
|
||||
* @param {number} x - Target item.
|
||||
* @return {number}
|
||||
*/
|
||||
StaticDisjointSet.prototype.find = function(x) {
|
||||
var y = x;
|
||||
|
||||
var c, p;
|
||||
|
||||
while (true) {
|
||||
c = this.parents[y];
|
||||
|
||||
if (y === c)
|
||||
break;
|
||||
|
||||
y = c;
|
||||
}
|
||||
|
||||
// Path compression
|
||||
while (true) {
|
||||
p = this.parents[x];
|
||||
|
||||
if (p === y)
|
||||
break;
|
||||
|
||||
this.parents[x] = y;
|
||||
x = p;
|
||||
}
|
||||
|
||||
return y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to perform the union of two items.
|
||||
*
|
||||
* @param {number} x - First item.
|
||||
* @param {number} y - Second item.
|
||||
* @return {StaticDisjointSet}
|
||||
*/
|
||||
StaticDisjointSet.prototype.union = function(x, y) {
|
||||
var xRoot = this.find(x),
|
||||
yRoot = this.find(y);
|
||||
|
||||
// x and y are already in the same set
|
||||
if (xRoot === yRoot)
|
||||
return this;
|
||||
|
||||
this.dimension--;
|
||||
|
||||
// x and y are not in the same set, we merge them
|
||||
var xRank = this.ranks[x],
|
||||
yRank = this.ranks[y];
|
||||
|
||||
if (xRank < yRank) {
|
||||
this.parents[xRoot] = yRoot;
|
||||
}
|
||||
else if (xRank > yRank) {
|
||||
this.parents[yRoot] = xRoot;
|
||||
}
|
||||
else {
|
||||
this.parents[yRoot] = xRoot;
|
||||
this.ranks[xRoot]++;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning whether two items are connected.
|
||||
*
|
||||
* @param {number} x - First item.
|
||||
* @param {number} y - Second item.
|
||||
* @return {boolean}
|
||||
*/
|
||||
StaticDisjointSet.prototype.connected = function(x, y) {
|
||||
var xRoot = this.find(x);
|
||||
|
||||
return xRoot === this.find(y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning the set mapping.
|
||||
*
|
||||
* @return {TypedArray}
|
||||
*/
|
||||
StaticDisjointSet.prototype.mapping = function() {
|
||||
var MappingClass = helpers.getPointerArray(this.dimension);
|
||||
|
||||
var ids = {},
|
||||
mapping = new MappingClass(this.size),
|
||||
c = 0;
|
||||
|
||||
var r;
|
||||
|
||||
for (var i = 0, l = this.parents.length; i < l; i++) {
|
||||
r = this.find(i);
|
||||
|
||||
if (typeof ids[r] === 'undefined') {
|
||||
mapping[i] = c;
|
||||
ids[r] = c++;
|
||||
}
|
||||
else {
|
||||
mapping[i] = ids[r];
|
||||
}
|
||||
}
|
||||
|
||||
return mapping;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to compile the disjoint set into an array of arrays.
|
||||
*
|
||||
* @return {array}
|
||||
*/
|
||||
StaticDisjointSet.prototype.compile = function() {
|
||||
var ids = {},
|
||||
result = new Array(this.dimension),
|
||||
c = 0;
|
||||
|
||||
var r;
|
||||
|
||||
for (var i = 0, l = this.parents.length; i < l; i++) {
|
||||
r = this.find(i);
|
||||
|
||||
if (typeof ids[r] === 'undefined') {
|
||||
result[c] = [i];
|
||||
ids[r] = c++;
|
||||
}
|
||||
else {
|
||||
result[ids[r]].push(i);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
StaticDisjointSet.prototype.inspect = function() {
|
||||
var array = this.compile();
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(array, 'constructor', {
|
||||
value: StaticDisjointSet,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
StaticDisjointSet.prototype[Symbol.for('nodejs.util.inspect.custom')] = StaticDisjointSet.prototype.inspect;
|
||||
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = StaticDisjointSet;
|
||||
27
backend/node_modules/mnemonist/static-interval-tree.d.ts
generated
vendored
Normal file
27
backend/node_modules/mnemonist/static-interval-tree.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Mnemonist StaticIntervalTree Typings
|
||||
* =====================================
|
||||
*/
|
||||
type StaticIntervalTreeGetter<T> = (item: T) => number;
|
||||
type StaticIntervalTreeGettersTuple<T> = [StaticIntervalTreeGetter<T>, StaticIntervalTreeGetter<T>];
|
||||
|
||||
export default class StaticIntervalTree<T> {
|
||||
|
||||
// Members
|
||||
height: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(intervals: Array<T>, getters?: StaticIntervalTreeGettersTuple<T>);
|
||||
|
||||
// Methods
|
||||
intervalsContainingPoint(point: number): Array<T>;
|
||||
intervalsOverlappingInterval(interval: T): Array<T>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(
|
||||
iterable: Iterable<I> | {[key: string]: I},
|
||||
getters?: StaticIntervalTreeGettersTuple<I>
|
||||
): StaticIntervalTree<I>;
|
||||
}
|
||||
387
backend/node_modules/mnemonist/static-interval-tree.js
generated
vendored
Normal file
387
backend/node_modules/mnemonist/static-interval-tree.js
generated
vendored
Normal file
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* Mnemonist StaticIntervalTree
|
||||
* =============================
|
||||
*
|
||||
* JavaScript implementation of a static interval tree. This tree is static in
|
||||
* that you are required to know all its items beforehand and to built it
|
||||
* from an iterable.
|
||||
*
|
||||
* This implementation represents the interval tree as an augmented balanced
|
||||
* binary search tree. It works by sorting the intervals by startpoint first
|
||||
* then proceeds building the augmented balanced BST bottom-up from the
|
||||
* sorted list.
|
||||
*
|
||||
* Note that this implementation considers every given intervals as closed for
|
||||
* simplicity's sake.
|
||||
*
|
||||
* For more information: https://en.wikipedia.org/wiki/Interval_tree
|
||||
*/
|
||||
var iterables = require('./utils/iterables.js'),
|
||||
typed = require('./utils/typed-arrays.js');
|
||||
|
||||
var FixedStack = require('./fixed-stack.js');
|
||||
|
||||
|
||||
// TODO: pass index to getters
|
||||
// TODO: custom comparison
|
||||
// TODO: possibility to pass offset buffer
|
||||
|
||||
// TODO: intervals() => Symbol.iterator
|
||||
// TODO: dfs()
|
||||
|
||||
/**
|
||||
* Helpers.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Recursive function building the BST from the sorted list of interval
|
||||
* indices.
|
||||
*
|
||||
* @param {array} intervals - Array of intervals to index.
|
||||
* @param {function} endGetter - Getter function for end of intervals.
|
||||
* @param {array} sortedIndices - Sorted indices of the intervals.
|
||||
* @param {array} tree - BST memory.
|
||||
* @param {array} augmentations - Array of node augmentations.
|
||||
* @param {number} i - BST index of current node.
|
||||
* @param {number} low - Dichotomy low index.
|
||||
* @param {number} high - Dichotomy high index.
|
||||
* @return {number} - Created node augmentation value.
|
||||
*/
|
||||
function buildBST(
|
||||
intervals,
|
||||
endGetter,
|
||||
sortedIndices,
|
||||
tree,
|
||||
augmentations,
|
||||
i,
|
||||
low,
|
||||
high
|
||||
) {
|
||||
var mid = (low + (high - low) / 2) | 0,
|
||||
midMinusOne = ~-mid,
|
||||
midPlusOne = -~mid;
|
||||
|
||||
var current = sortedIndices[mid];
|
||||
tree[i] = current + 1;
|
||||
|
||||
var end = endGetter ? endGetter(intervals[current]) : intervals[current][1];
|
||||
|
||||
var left = i * 2 + 1,
|
||||
right = i * 2 + 2;
|
||||
|
||||
var leftEnd = -Infinity,
|
||||
rightEnd = -Infinity;
|
||||
|
||||
if (low <= midMinusOne) {
|
||||
leftEnd = buildBST(
|
||||
intervals,
|
||||
endGetter,
|
||||
sortedIndices,
|
||||
tree,
|
||||
augmentations,
|
||||
left,
|
||||
low,
|
||||
midMinusOne
|
||||
);
|
||||
}
|
||||
|
||||
if (midPlusOne <= high) {
|
||||
rightEnd = buildBST(
|
||||
intervals,
|
||||
endGetter,
|
||||
sortedIndices,
|
||||
tree,
|
||||
augmentations,
|
||||
right,
|
||||
midPlusOne,
|
||||
high
|
||||
);
|
||||
}
|
||||
|
||||
var augmentation = Math.max(end, leftEnd, rightEnd);
|
||||
|
||||
var augmentationPointer = current;
|
||||
|
||||
if (augmentation === leftEnd)
|
||||
augmentationPointer = augmentations[tree[left] - 1];
|
||||
else if (augmentation === rightEnd)
|
||||
augmentationPointer = augmentations[tree[right] - 1];
|
||||
|
||||
augmentations[current] = augmentationPointer;
|
||||
|
||||
return augmentation;
|
||||
}
|
||||
|
||||
/**
|
||||
* StaticIntervalTree.
|
||||
*
|
||||
* @constructor
|
||||
* @param {array} intervals - Array of intervals to index.
|
||||
* @param {array<function>} getters - Optional getters.
|
||||
*/
|
||||
function StaticIntervalTree(intervals, getters) {
|
||||
|
||||
// Properties
|
||||
this.size = intervals.length;
|
||||
this.intervals = intervals;
|
||||
|
||||
var startGetter = null,
|
||||
endGetter = null;
|
||||
|
||||
if (Array.isArray(getters)) {
|
||||
startGetter = getters[0];
|
||||
endGetter = getters[1];
|
||||
}
|
||||
|
||||
// Building the indices array
|
||||
var length = intervals.length;
|
||||
|
||||
var IndicesArray = typed.getPointerArray(length + 1);
|
||||
|
||||
var indices = new IndicesArray(length);
|
||||
|
||||
var i;
|
||||
|
||||
for (i = 1; i < length; i++)
|
||||
indices[i] = i;
|
||||
|
||||
// Sorting indices array
|
||||
// TODO: check if some version of radix sort can outperform this part
|
||||
indices.sort(function(a, b) {
|
||||
a = intervals[a];
|
||||
b = intervals[b];
|
||||
|
||||
if (startGetter) {
|
||||
a = startGetter(a);
|
||||
b = startGetter(b);
|
||||
}
|
||||
else {
|
||||
a = a[0];
|
||||
b = b[0];
|
||||
}
|
||||
|
||||
if (a < b)
|
||||
return -1;
|
||||
|
||||
if (a > b)
|
||||
return 1;
|
||||
|
||||
// TODO: use getters
|
||||
// TODO: this ordering has the following invariant: if query interval
|
||||
// contains [nodeStart, max], then whole right subtree can be collected
|
||||
// a = a[1];
|
||||
// b = b[1];
|
||||
|
||||
// if (a < b)
|
||||
// return 1;
|
||||
|
||||
// if (a > b)
|
||||
// return -1;
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
// Building the binary tree
|
||||
var height = Math.ceil(Math.log2(length + 1)),
|
||||
treeSize = Math.pow(2, height) - 1;
|
||||
|
||||
var tree = new IndicesArray(treeSize);
|
||||
|
||||
var augmentations = new IndicesArray(length);
|
||||
|
||||
buildBST(
|
||||
intervals,
|
||||
endGetter,
|
||||
indices,
|
||||
tree,
|
||||
augmentations,
|
||||
0,
|
||||
0,
|
||||
length - 1
|
||||
);
|
||||
|
||||
// Dropping indices
|
||||
indices = null;
|
||||
|
||||
// Storing necessary information
|
||||
this.height = height;
|
||||
this.tree = tree;
|
||||
this.augmentations = augmentations;
|
||||
this.startGetter = startGetter;
|
||||
this.endGetter = endGetter;
|
||||
|
||||
// Initializing DFS stack
|
||||
this.stack = new FixedStack(IndicesArray, this.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method returning a list of intervals containing the given point.
|
||||
*
|
||||
* @param {any} point - Target point.
|
||||
* @return {array}
|
||||
*/
|
||||
StaticIntervalTree.prototype.intervalsContainingPoint = function(point) {
|
||||
var matches = [];
|
||||
|
||||
var stack = this.stack;
|
||||
|
||||
stack.clear();
|
||||
stack.push(0);
|
||||
|
||||
var l = this.tree.length;
|
||||
|
||||
var bstIndex,
|
||||
intervalIndex,
|
||||
interval,
|
||||
maxInterval,
|
||||
start,
|
||||
end,
|
||||
max,
|
||||
left,
|
||||
right;
|
||||
|
||||
while (stack.size) {
|
||||
bstIndex = stack.pop();
|
||||
intervalIndex = this.tree[bstIndex] - 1;
|
||||
interval = this.intervals[intervalIndex];
|
||||
maxInterval = this.intervals[this.augmentations[intervalIndex]];
|
||||
|
||||
max = this.endGetter ? this.endGetter(maxInterval) : maxInterval[1];
|
||||
|
||||
// No possible match, point is farther right than the max end value
|
||||
if (point > max)
|
||||
continue;
|
||||
|
||||
// Searching left
|
||||
left = bstIndex * 2 + 1;
|
||||
|
||||
if (left < l && this.tree[left] !== 0)
|
||||
stack.push(left);
|
||||
|
||||
start = this.startGetter ? this.startGetter(interval) : interval[0];
|
||||
end = this.endGetter ? this.endGetter(interval) : interval[1];
|
||||
|
||||
// Checking current node
|
||||
if (point >= start && point <= end)
|
||||
matches.push(interval);
|
||||
|
||||
// If the point is to the left of the start of the current interval,
|
||||
// then it cannot be in the right child
|
||||
if (point < start)
|
||||
continue;
|
||||
|
||||
// Searching right
|
||||
right = bstIndex * 2 + 2;
|
||||
|
||||
if (right < l && this.tree[right] !== 0)
|
||||
stack.push(right);
|
||||
}
|
||||
|
||||
return matches;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning a list of intervals overlapping the given interval.
|
||||
*
|
||||
* @param {any} interval - Target interval.
|
||||
* @return {array}
|
||||
*/
|
||||
StaticIntervalTree.prototype.intervalsOverlappingInterval = function(interval) {
|
||||
var intervalStart = this.startGetter ? this.startGetter(interval) : interval[0],
|
||||
intervalEnd = this.endGetter ? this.endGetter(interval) : interval[1];
|
||||
|
||||
var matches = [];
|
||||
|
||||
var stack = this.stack;
|
||||
|
||||
stack.clear();
|
||||
stack.push(0);
|
||||
|
||||
var l = this.tree.length;
|
||||
|
||||
var bstIndex,
|
||||
intervalIndex,
|
||||
currentInterval,
|
||||
maxInterval,
|
||||
start,
|
||||
end,
|
||||
max,
|
||||
left,
|
||||
right;
|
||||
|
||||
while (stack.size) {
|
||||
bstIndex = stack.pop();
|
||||
intervalIndex = this.tree[bstIndex] - 1;
|
||||
currentInterval = this.intervals[intervalIndex];
|
||||
maxInterval = this.intervals[this.augmentations[intervalIndex]];
|
||||
|
||||
max = this.endGetter ? this.endGetter(maxInterval) : maxInterval[1];
|
||||
|
||||
// No possible match, start is farther right than the max end value
|
||||
if (intervalStart > max)
|
||||
continue;
|
||||
|
||||
// Searching left
|
||||
left = bstIndex * 2 + 1;
|
||||
|
||||
if (left < l && this.tree[left] !== 0)
|
||||
stack.push(left);
|
||||
|
||||
start = this.startGetter ? this.startGetter(currentInterval) : currentInterval[0];
|
||||
end = this.endGetter ? this.endGetter(currentInterval) : currentInterval[1];
|
||||
|
||||
// Checking current node
|
||||
if (intervalEnd >= start && intervalStart <= end)
|
||||
matches.push(currentInterval);
|
||||
|
||||
// If the end is to the left of the start of the current interval,
|
||||
// then it cannot be in the right child
|
||||
if (intervalEnd < start)
|
||||
continue;
|
||||
|
||||
// Searching right
|
||||
right = bstIndex * 2 + 2;
|
||||
|
||||
if (right < l && this.tree[right] !== 0)
|
||||
stack.push(right);
|
||||
}
|
||||
|
||||
return matches;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
StaticIntervalTree.prototype.inspect = function() {
|
||||
var proxy = this.intervals.slice();
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: StaticIntervalTree,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
StaticIntervalTree.prototype[Symbol.for('nodejs.util.inspect.custom')] = StaticIntervalTree.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a structure.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @return {StaticIntervalTree}
|
||||
*/
|
||||
StaticIntervalTree.from = function(iterable, getters) {
|
||||
if (iterables.isArrayLike(iterable))
|
||||
return new StaticIntervalTree(iterable, getters);
|
||||
|
||||
return new StaticIntervalTree(Array.from(iterable), getters);
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = StaticIntervalTree;
|
||||
37
backend/node_modules/mnemonist/suffix-array.d.ts
generated
vendored
Normal file
37
backend/node_modules/mnemonist/suffix-array.d.ts
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Mnemonist SuffixArray Typings
|
||||
* ==============================
|
||||
*/
|
||||
export default class SuffixArray {
|
||||
|
||||
// Members
|
||||
array: Array<number>;
|
||||
length: number;
|
||||
string: string | Array<string>;
|
||||
|
||||
// Constructor
|
||||
constructor(string: string | Array<string>);
|
||||
|
||||
// Methods
|
||||
toString(): string;
|
||||
toJSON(): Array<number>;
|
||||
inspect(): any;
|
||||
}
|
||||
|
||||
export class GeneralizedSuffixArray {
|
||||
|
||||
// Members
|
||||
array: Array<number>;
|
||||
length: number;
|
||||
size: number;
|
||||
text: string | Array<string>;
|
||||
|
||||
// Constructor
|
||||
constructor(strings: Array<string> | Array<Array<string>>);
|
||||
|
||||
// Methods
|
||||
longestCommonSubsequence(): string | Array<string>;
|
||||
toString(): string;
|
||||
toJSON(): Array<number>;
|
||||
inspect(): any;
|
||||
}
|
||||
352
backend/node_modules/mnemonist/suffix-array.js
generated
vendored
Normal file
352
backend/node_modules/mnemonist/suffix-array.js
generated
vendored
Normal file
@@ -0,0 +1,352 @@
|
||||
/**
|
||||
* Mnemonist Suffix Array
|
||||
* =======================
|
||||
*
|
||||
* Linear time implementation of a suffix array using the recursive
|
||||
* method by Karkkainen and Sanders.
|
||||
*
|
||||
* [References]:
|
||||
* https://www.cs.helsinki.fi/u/tpkarkka/publications/jacm05-revised.pdf
|
||||
* http://people.mpi-inf.mpg.de/~sanders/programs/suffix/
|
||||
* http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.184.442&rep=rep1&type=pdf
|
||||
*
|
||||
* [Article]:
|
||||
* "Simple Linear Work Suffix Array Construction", Karkkainen and Sanders.
|
||||
*
|
||||
* [Note]:
|
||||
* A paper by Simon J. Puglisi, William F. Smyth & Andrew Turpin named
|
||||
* "The Performance of Linear Time Suffix Sorting Algorithms" seems to
|
||||
* prove that supralinear algorithm are in fact better faring for
|
||||
* "real" world use cases. It would be nice to check this out in JavaScript
|
||||
* because the high level of the language could change a lot to the fact.
|
||||
*
|
||||
* The current code is largely inspired by the following:
|
||||
* https://github.com/tixxit/suffixarray/blob/master/suffixarray.js
|
||||
*/
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
*/
|
||||
var SEPARATOR = '\u0001';
|
||||
|
||||
/**
|
||||
* Function used to sort the triples.
|
||||
*
|
||||
* @param {string|array} string - Padded sequence.
|
||||
* @param {array} array - Array to sort (will be mutated).
|
||||
* @param {number} offset - Index offset.
|
||||
*/
|
||||
function sort(string, array, offset) {
|
||||
var l = array.length,
|
||||
buckets = [],
|
||||
i = l,
|
||||
j = -1,
|
||||
b,
|
||||
d = 0,
|
||||
bits;
|
||||
|
||||
while (i--)
|
||||
j = Math.max(string[array[i] + offset], j);
|
||||
|
||||
bits = j >> 24 && 32 || j >> 16 && 24 || j >> 8 && 16 || 8;
|
||||
|
||||
for (; d < bits; d += 4) {
|
||||
for (i = 16; i--;)
|
||||
buckets[i] = [];
|
||||
for (i = l; i--;)
|
||||
buckets[((string[array[i] + offset]) >> d) & 15].push(array[i]);
|
||||
for (b = 0; b < 16; b++) {
|
||||
for (j = buckets[b].length; j--;)
|
||||
array[++i] = buckets[b][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparison helper.
|
||||
*/
|
||||
function compare(string, lookup, m, n) {
|
||||
return (
|
||||
(string[m] - string[n]) ||
|
||||
(m % 3 === 2 ?
|
||||
(string[m + 1] - string[n + 1]) || (lookup[m + 2] - lookup[n + 2]) :
|
||||
(lookup[m + 1] - lookup[n + 1]))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive function used to build the suffix tree in linear time.
|
||||
*
|
||||
* @param {string|array} string - Padded sequence.
|
||||
* @param {number} l - True length of sequence (unpadded).
|
||||
* @return {array}
|
||||
*/
|
||||
function build(string, l) {
|
||||
var a = [],
|
||||
b = [],
|
||||
al = (2 * l / 3) | 0,
|
||||
bl = l - al,
|
||||
r = (al + 1) >> 1,
|
||||
i = al,
|
||||
j = 0,
|
||||
k,
|
||||
lookup = [],
|
||||
result = [];
|
||||
|
||||
if (l === 1)
|
||||
return [0];
|
||||
|
||||
while (i--)
|
||||
a[i] = ((i * 3) >> 1) + 1;
|
||||
|
||||
for (i = 3; i--;)
|
||||
sort(string, a, i);
|
||||
|
||||
j = b[((a[0] / 3) | 0) + (a[0] % 3 === 1 ? 0 : r)] = 1;
|
||||
|
||||
for (i = 1; i < al; i++) {
|
||||
if (string[a[i]] !== string[a[i - 1]] ||
|
||||
string[a[i] + 1] !== string[a[i - 1] + 1] ||
|
||||
string[a[i] + 2] !== string[a[i - 1] + 2])
|
||||
j++;
|
||||
|
||||
b[((a[i] / 3) | 0) + (a[i] % 3 === 1 ? 0 : r)] = j;
|
||||
}
|
||||
|
||||
if (j < al) {
|
||||
b = build(b, al);
|
||||
|
||||
for (i = al; i--;)
|
||||
a[i] = b[i] < r ? b[i] * 3 + 1 : ((b[i] - r) * 3 + 2);
|
||||
}
|
||||
|
||||
for (i = al; i--;)
|
||||
lookup[a[i]] = i;
|
||||
lookup[l] = -1;
|
||||
lookup[l + 1] = -2;
|
||||
|
||||
b = l % 3 === 1 ? [l - 1] : [];
|
||||
|
||||
for (i = 0; i < al; i++) {
|
||||
if (a[i] % 3 === 1)
|
||||
b.push(a[i] - 1);
|
||||
}
|
||||
|
||||
sort(string, b, 0);
|
||||
|
||||
for (i = 0, j = 0, k = 0; i < al && j < bl;)
|
||||
result[k++] = (
|
||||
compare(string, lookup, a[i], b[j]) < 0 ?
|
||||
a[i++] :
|
||||
b[j++]
|
||||
);
|
||||
|
||||
while (i < al)
|
||||
result[k++] = a[i++];
|
||||
|
||||
while (j < bl)
|
||||
result[k++] = b[j++];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to create the array we are going to work on.
|
||||
*
|
||||
* @param {string|array} target - Target sequence.
|
||||
* @return {array}
|
||||
*/
|
||||
function convert(target) {
|
||||
|
||||
// Creating the alphabet array
|
||||
var length = target.length,
|
||||
paddingOffset = length % 3,
|
||||
array = new Array(length + paddingOffset),
|
||||
l,
|
||||
i;
|
||||
|
||||
// If we have an arbitrary sequence, we need to transform it
|
||||
if (typeof target !== 'string') {
|
||||
var uniqueTokens = Object.create(null);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (!uniqueTokens[target[i]])
|
||||
uniqueTokens[target[i]] = true;
|
||||
}
|
||||
|
||||
var alphabet = Object.create(null),
|
||||
sortedUniqueTokens = Object.keys(uniqueTokens).sort();
|
||||
|
||||
for (i = 0, l = sortedUniqueTokens.length; i < l; i++)
|
||||
alphabet[sortedUniqueTokens[i]] = i + 1;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
array[i] = alphabet[target[i]];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < length; i++)
|
||||
array[i] = target.charCodeAt(i);
|
||||
}
|
||||
|
||||
// Padding the array
|
||||
for (i = length; i < length + paddingOffset; i++)
|
||||
array[i] = 0;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Suffix Array.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string|array} string - Sequence for which to build the suffix array.
|
||||
*/
|
||||
function SuffixArray(string) {
|
||||
|
||||
// Properties
|
||||
this.hasArbitrarySequence = typeof string !== 'string';
|
||||
this.string = string;
|
||||
this.length = string.length;
|
||||
|
||||
// Building the array
|
||||
this.array = build(convert(string), this.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
SuffixArray.prototype.toString = function() {
|
||||
return this.array.join(',');
|
||||
};
|
||||
|
||||
SuffixArray.prototype.toJSON = function() {
|
||||
return this.array;
|
||||
};
|
||||
|
||||
SuffixArray.prototype.inspect = function() {
|
||||
var array = new Array(this.length);
|
||||
|
||||
for (var i = 0; i < this.length; i++)
|
||||
array[i] = this.string.slice(this.array[i]);
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(array, 'constructor', {
|
||||
value: SuffixArray,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
SuffixArray.prototype[Symbol.for('nodejs.util.inspect.custom')] = SuffixArray.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Generalized Suffix Array.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function GeneralizedSuffixArray(strings) {
|
||||
|
||||
// Properties
|
||||
this.hasArbitrarySequence = typeof strings[0] !== 'string';
|
||||
this.size = strings.length;
|
||||
|
||||
if (this.hasArbitrarySequence) {
|
||||
this.text = [];
|
||||
|
||||
for (var i = 0, l = this.size; i < l; i++) {
|
||||
this.text.push.apply(this.text, strings[i]);
|
||||
|
||||
if (i < l - 1)
|
||||
this.text.push(SEPARATOR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.text = strings.join(SEPARATOR);
|
||||
}
|
||||
|
||||
this.firstLength = strings[0].length;
|
||||
this.length = this.text.length;
|
||||
|
||||
// Building the array
|
||||
this.array = build(convert(this.text), this.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to retrieve the longest common subsequence of the generalized
|
||||
* suffix array.
|
||||
*
|
||||
* @return {string|array}
|
||||
*/
|
||||
GeneralizedSuffixArray.prototype.longestCommonSubsequence = function() {
|
||||
var lcs = this.hasArbitrarySequence ? [] : '',
|
||||
lcp,
|
||||
i,
|
||||
j,
|
||||
s,
|
||||
t;
|
||||
|
||||
for (i = 1; i < this.length; i++) {
|
||||
s = this.array[i];
|
||||
t = this.array[i - 1];
|
||||
|
||||
if (s < this.firstLength &&
|
||||
t < this.firstLength)
|
||||
continue;
|
||||
|
||||
if (s > this.firstLength &&
|
||||
t > this.firstLength)
|
||||
continue;
|
||||
|
||||
lcp = Math.min(this.length - s, this.length - t);
|
||||
|
||||
for (j = 0; j < lcp; j++) {
|
||||
if (this.text[s + j] !== this.text[t + j]) {
|
||||
lcp = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lcp > lcs.length)
|
||||
lcs = this.text.slice(s, s + lcp);
|
||||
}
|
||||
|
||||
return lcs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
GeneralizedSuffixArray.prototype.toString = function() {
|
||||
return this.array.join(',');
|
||||
};
|
||||
|
||||
GeneralizedSuffixArray.prototype.toJSON = function() {
|
||||
return this.array;
|
||||
};
|
||||
|
||||
GeneralizedSuffixArray.prototype.inspect = function() {
|
||||
var array = new Array(this.length);
|
||||
|
||||
for (var i = 0; i < this.length; i++)
|
||||
array[i] = this.text.slice(this.array[i]);
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(array, 'constructor', {
|
||||
value: GeneralizedSuffixArray,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
GeneralizedSuffixArray.prototype[Symbol.for('nodejs.util.inspect.custom')] = GeneralizedSuffixArray.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
SuffixArray.GeneralizedSuffixArray = GeneralizedSuffixArray;
|
||||
module.exports = SuffixArray;
|
||||
33
backend/node_modules/mnemonist/symspell.d.ts
generated
vendored
Normal file
33
backend/node_modules/mnemonist/symspell.d.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Mnemonist SymSpell Typings
|
||||
* ===========================
|
||||
*/
|
||||
type SymSpellVerbosity = 0 | 1 | 2;
|
||||
|
||||
type SymSpellOptions = {
|
||||
maxDistance?: number;
|
||||
verbosity?: SymSpellVerbosity
|
||||
};
|
||||
|
||||
type SymSpellMatch = {
|
||||
term: string;
|
||||
distance: number;
|
||||
count: number;
|
||||
}
|
||||
|
||||
export default class SymSpell {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(options?: SymSpellOptions);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
add(string: string): this;
|
||||
search(query: string): Array<SymSpellMatch>;
|
||||
|
||||
// Statics
|
||||
static from(strings: Iterable<string> | {[key: string]: string}, options?: SymSpellOptions): SymSpell;
|
||||
}
|
||||
547
backend/node_modules/mnemonist/symspell.js
generated
vendored
Normal file
547
backend/node_modules/mnemonist/symspell.js
generated
vendored
Normal file
@@ -0,0 +1,547 @@
|
||||
/* eslint no-loop-func: 0 */
|
||||
/**
|
||||
* Mnemonist SymSpell
|
||||
* ===================
|
||||
*
|
||||
* JavaScript implementation of the Symmetric Delete Spelling dictionary to
|
||||
* efficiently index & query expression based on edit distance.
|
||||
* Note that the current implementation target the v3.0 of the algorithm.
|
||||
*
|
||||
* [Reference]:
|
||||
* http://blog.faroo.com/2012/06/07/improved-edit-distance-based-spelling-correction/
|
||||
* https://github.com/wolfgarbe/symspell
|
||||
*
|
||||
* [Author]:
|
||||
* Wolf Garbe
|
||||
*/
|
||||
var forEach = require('obliterator/foreach');
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
*/
|
||||
var DEFAULT_MAX_DISTANCE = 2,
|
||||
DEFAULT_VERBOSITY = 2;
|
||||
|
||||
var VERBOSITY = new Set([
|
||||
// Returns only the top suggestion
|
||||
0,
|
||||
// Returns suggestions with the smallest edit distance
|
||||
1,
|
||||
// Returns every suggestion (no early termination)
|
||||
2
|
||||
]);
|
||||
|
||||
var VERBOSITY_EXPLANATIONS = {
|
||||
0: 'Returns only the top suggestion',
|
||||
1: 'Returns suggestions with the smallest edit distance',
|
||||
2: 'Returns every suggestion (no early termination)'
|
||||
};
|
||||
|
||||
/**
|
||||
* Functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Function creating a dictionary item.
|
||||
*
|
||||
* @param {number} [value] - An optional suggestion.
|
||||
* @return {object} - The created item.
|
||||
*/
|
||||
function createDictionaryItem(value) {
|
||||
var suggestions = new Set();
|
||||
|
||||
if (typeof value === 'number')
|
||||
suggestions.add(value);
|
||||
|
||||
return {
|
||||
suggestions,
|
||||
count: 0
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Function creating a suggestion item.
|
||||
*
|
||||
* @return {object} - The created item.
|
||||
*/
|
||||
function createSuggestionItem(term, distance, count) {
|
||||
return {
|
||||
term: term || '',
|
||||
distance: distance || 0,
|
||||
count: count || 0
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified edit function.
|
||||
*
|
||||
* @param {string} word - Target word.
|
||||
* @param {number} distance - Distance.
|
||||
* @param {number} max - Max distance.
|
||||
* @param {Set} [deletes] - Set mutated to store deletes.
|
||||
*/
|
||||
function edits(word, distance, max, deletes) {
|
||||
deletes = deletes || new Set();
|
||||
distance++;
|
||||
|
||||
var deletedItem,
|
||||
l = word.length,
|
||||
i;
|
||||
|
||||
if (l > 1) {
|
||||
for (i = 0; i < l; i++) {
|
||||
deletedItem = word.substring(0, i) + word.substring(i + 1);
|
||||
|
||||
if (!deletes.has(deletedItem)) {
|
||||
deletes.add(deletedItem);
|
||||
|
||||
if (distance < max)
|
||||
edits(deletedItem, distance, max, deletes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return deletes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to conditionally add suggestions.
|
||||
*
|
||||
* @param {array} words - Words list.
|
||||
* @param {number} verbosity - Verbosity level.
|
||||
* @param {object} item - The target item.
|
||||
* @param {string} suggestion - The target suggestion.
|
||||
* @param {number} int - Integer key of the word.
|
||||
* @param {object} deletedItem - Considered deleted item.
|
||||
* @param {SymSpell}
|
||||
*/
|
||||
function addLowestDistance(words, verbosity, item, suggestion, int, deletedItem) {
|
||||
var first = item.suggestions.values().next().value;
|
||||
|
||||
if (verbosity < 2 &&
|
||||
item.suggestions.size > 0 &&
|
||||
words[first].length - deletedItem.length > suggestion.length - deletedItem.length) {
|
||||
item.suggestions = new Set();
|
||||
item.count = 0;
|
||||
}
|
||||
|
||||
if (verbosity === 2 ||
|
||||
!item.suggestions.size ||
|
||||
words[first].length - deletedItem.length >= suggestion.length - deletedItem.length) {
|
||||
item.suggestions.add(int);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom Damerau-Levenshtein used by the algorithm.
|
||||
*
|
||||
* @param {string} source - First string.
|
||||
* @param {string} target - Second string.
|
||||
* @return {number} - The distance.
|
||||
*/
|
||||
function damerauLevenshtein(source, target) {
|
||||
var m = source.length,
|
||||
n = target.length,
|
||||
H = [[]],
|
||||
INF = m + n,
|
||||
sd = new Map(),
|
||||
i,
|
||||
l,
|
||||
j;
|
||||
|
||||
H[0][0] = INF;
|
||||
|
||||
for (i = 0; i <= m; i++) {
|
||||
if (!H[i + 1])
|
||||
H[i + 1] = [];
|
||||
H[i + 1][1] = i;
|
||||
H[i + 1][0] = INF;
|
||||
}
|
||||
|
||||
for (j = 0; j <= n; j++) {
|
||||
H[1][j + 1] = j;
|
||||
H[0][j + 1] = INF;
|
||||
}
|
||||
|
||||
var st = source + target,
|
||||
letter;
|
||||
|
||||
for (i = 0, l = st.length; i < l; i++) {
|
||||
letter = st[i];
|
||||
|
||||
if (!sd.has(letter))
|
||||
sd.set(letter, 0);
|
||||
}
|
||||
|
||||
// Iterating
|
||||
for (i = 1; i <= m; i++) {
|
||||
var DB = 0;
|
||||
|
||||
for (j = 1; j <= n; j++) {
|
||||
var i1 = sd.get(target[j - 1]),
|
||||
j1 = DB;
|
||||
|
||||
if (source[i - 1] === target[j - 1]) {
|
||||
H[i + 1][j + 1] = H[i][j];
|
||||
DB = j;
|
||||
}
|
||||
else {
|
||||
H[i + 1][j + 1] = Math.min(
|
||||
H[i][j],
|
||||
H[i + 1][j],
|
||||
H[i][j + 1]
|
||||
) + 1;
|
||||
}
|
||||
|
||||
H[i + 1][j + 1] = Math.min(
|
||||
H[i + 1][j + 1],
|
||||
H[i1][j1] + (i - i1 - 1) + 1 + (j - j1 - 1)
|
||||
);
|
||||
}
|
||||
|
||||
sd.set(source[i - 1], i);
|
||||
}
|
||||
|
||||
return H[m + 1][n + 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup function.
|
||||
*
|
||||
* @param {object} dictionary - A SymSpell dictionary.
|
||||
* @param {array} words - Unique words list.
|
||||
* @param {number} verbosity - Verbosity level.
|
||||
* @param {number} maxDistance - Maximum distance.
|
||||
* @param {number} maxLength - Maximum word length in the dictionary.
|
||||
* @param {string} input - Input string.
|
||||
* @return {array} - The list of suggestions.
|
||||
*/
|
||||
function lookup(dictionary, words, verbosity, maxDistance, maxLength, input) {
|
||||
var length = input.length;
|
||||
|
||||
if (length - maxDistance > maxLength)
|
||||
return [];
|
||||
|
||||
var candidates = [input],
|
||||
candidateSet = new Set(),
|
||||
suggestionSet = new Set();
|
||||
|
||||
var suggestions = [],
|
||||
candidate,
|
||||
item;
|
||||
|
||||
// Exhausting every candidates
|
||||
while (candidates.length > 0) {
|
||||
candidate = candidates.shift();
|
||||
|
||||
// Early termination
|
||||
if (
|
||||
verbosity < 2 &&
|
||||
suggestions.length > 0 &&
|
||||
length - candidate.length > suggestions[0].distance
|
||||
)
|
||||
break;
|
||||
|
||||
item = dictionary[candidate];
|
||||
|
||||
if (item !== undefined) {
|
||||
if (typeof item === 'number')
|
||||
item = createDictionaryItem(item);
|
||||
|
||||
if (item.count > 0 && !suggestionSet.has(candidate)) {
|
||||
suggestionSet.add(candidate);
|
||||
|
||||
var suggestItem = createSuggestionItem(
|
||||
candidate,
|
||||
length - candidate.length,
|
||||
item.count
|
||||
);
|
||||
|
||||
suggestions.push(suggestItem);
|
||||
|
||||
// Another early termination
|
||||
if (verbosity < 2 && length - candidate.length === 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// Iterating over the item's suggestions
|
||||
item.suggestions.forEach(index => {
|
||||
var suggestion = words[index];
|
||||
|
||||
// Do we already have this suggestion?
|
||||
if (suggestionSet.has(suggestion))
|
||||
return;
|
||||
|
||||
suggestionSet.add(suggestion);
|
||||
|
||||
// Computing distance between candidate & suggestion
|
||||
var distance = 0;
|
||||
|
||||
if (input !== suggestion) {
|
||||
if (suggestion.length === candidate.length) {
|
||||
distance = length - candidate.length;
|
||||
}
|
||||
else if (length === candidate.length) {
|
||||
distance = suggestion.length - candidate.length;
|
||||
}
|
||||
else {
|
||||
var ii = 0,
|
||||
jj = 0;
|
||||
|
||||
var l = suggestion.length;
|
||||
|
||||
while (
|
||||
ii < l &&
|
||||
ii < length &&
|
||||
suggestion[ii] === input[ii]
|
||||
) {
|
||||
ii++;
|
||||
}
|
||||
|
||||
while (
|
||||
jj < l - ii &&
|
||||
jj < length &&
|
||||
suggestion[l - jj - 1] === input[length - jj - 1]
|
||||
) {
|
||||
jj++;
|
||||
}
|
||||
|
||||
if (ii > 0 || jj > 0) {
|
||||
distance = damerauLevenshtein(
|
||||
suggestion.substr(ii, l - ii - jj),
|
||||
input.substr(ii, length - ii - jj)
|
||||
);
|
||||
}
|
||||
else {
|
||||
distance = damerauLevenshtein(suggestion, input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Removing suggestions of higher distance
|
||||
if (verbosity < 2 &&
|
||||
suggestions.length > 0 &&
|
||||
suggestions[0].distance > distance) {
|
||||
suggestions = [];
|
||||
}
|
||||
|
||||
if (verbosity < 2 &&
|
||||
suggestions.length > 0 &&
|
||||
distance > suggestions[0].distance) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (distance <= maxDistance) {
|
||||
var target = dictionary[suggestion];
|
||||
|
||||
if (target !== undefined) {
|
||||
suggestions.push(createSuggestionItem(
|
||||
suggestion,
|
||||
distance,
|
||||
target.count
|
||||
));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Adding edits
|
||||
if (length - candidate.length < maxDistance) {
|
||||
|
||||
if (verbosity < 2 &&
|
||||
suggestions.length > 0 &&
|
||||
length - candidate.length >= suggestions[0].distance)
|
||||
continue;
|
||||
|
||||
for (var i = 0, l = candidate.length; i < l; i++) {
|
||||
var deletedItem = (
|
||||
candidate.substring(0, i) +
|
||||
candidate.substring(i + 1)
|
||||
);
|
||||
|
||||
if (!candidateSet.has(deletedItem)) {
|
||||
candidateSet.add(deletedItem);
|
||||
candidates.push(deletedItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (verbosity === 0)
|
||||
return suggestions.slice(0, 1);
|
||||
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
/**
|
||||
* SymSpell.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function SymSpell(options) {
|
||||
options = options || {};
|
||||
|
||||
this.clear();
|
||||
|
||||
// Properties
|
||||
this.maxDistance = typeof options.maxDistance === 'number' ?
|
||||
options.maxDistance :
|
||||
DEFAULT_MAX_DISTANCE;
|
||||
this.verbosity = typeof options.verbosity === 'number' ?
|
||||
options.verbosity :
|
||||
DEFAULT_VERBOSITY;
|
||||
|
||||
// Sanity checks
|
||||
if (typeof this.maxDistance !== 'number' || this.maxDistance <= 0)
|
||||
throw Error('mnemonist/SymSpell.constructor: invalid `maxDistance` option. Should be a integer greater than 0.');
|
||||
|
||||
if (!VERBOSITY.has(this.verbosity))
|
||||
throw Error('mnemonist/SymSpell.constructor: invalid `verbosity` option. Should be either 0, 1 or 2.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the structure.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
SymSpell.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.size = 0;
|
||||
this.dictionary = Object.create(null);
|
||||
this.maxLength = 0;
|
||||
this.words = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to add a word to the index.
|
||||
*
|
||||
* @param {string} word - Word to add.
|
||||
* @param {SymSpell}
|
||||
*/
|
||||
SymSpell.prototype.add = function(word) {
|
||||
var item = this.dictionary[word];
|
||||
|
||||
if (item !== undefined) {
|
||||
if (typeof item === 'number') {
|
||||
item = createDictionaryItem(item);
|
||||
this.dictionary[word] = item;
|
||||
}
|
||||
|
||||
item.count++;
|
||||
}
|
||||
|
||||
else {
|
||||
item = createDictionaryItem();
|
||||
item.count++;
|
||||
|
||||
this.dictionary[word] = item;
|
||||
|
||||
if (word.length > this.maxLength)
|
||||
this.maxLength = word.length;
|
||||
}
|
||||
|
||||
if (item.count === 1) {
|
||||
var number = this.words.length;
|
||||
this.words.push(word);
|
||||
|
||||
var deletes = edits(word, 0, this.maxDistance);
|
||||
|
||||
deletes.forEach(deletedItem => {
|
||||
var target = this.dictionary[deletedItem];
|
||||
|
||||
if (target !== undefined) {
|
||||
if (typeof target === 'number') {
|
||||
target = createDictionaryItem(target);
|
||||
|
||||
this.dictionary[deletedItem] = target;
|
||||
}
|
||||
|
||||
if (!target.suggestions.has(number)) {
|
||||
addLowestDistance(
|
||||
this.words,
|
||||
this.verbosity,
|
||||
target,
|
||||
word,
|
||||
number,
|
||||
deletedItem
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.dictionary[deletedItem] = number;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.size++;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to search the index.
|
||||
*
|
||||
* @param {string} input - Input query.
|
||||
* @return {array} - The found suggestions.
|
||||
*/
|
||||
SymSpell.prototype.search = function(input) {
|
||||
return lookup(
|
||||
this.dictionary,
|
||||
this.words,
|
||||
this.verbosity,
|
||||
this.maxDistance,
|
||||
this.maxLength,
|
||||
input
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
SymSpell.prototype.inspect = function() {
|
||||
var array = [];
|
||||
|
||||
array.size = this.size;
|
||||
array.maxDistance = this.maxDistance;
|
||||
array.verbosity = this.verbosity;
|
||||
array.behavior = VERBOSITY_EXPLANATIONS[this.verbosity];
|
||||
|
||||
for (var k in this.dictionary) {
|
||||
if (typeof this.dictionary[k] === 'object' && this.dictionary[k].count)
|
||||
array.push([k, this.dictionary[k].count]);
|
||||
}
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(array, 'constructor', {
|
||||
value: SymSpell,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
SymSpell.prototype[Symbol.for('nodejs.util.inspect.custom')] = SymSpell.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a structure.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @return {SymSpell}
|
||||
*/
|
||||
SymSpell.from = function(iterable, options) {
|
||||
var index = new SymSpell(options);
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
index.add(value);
|
||||
});
|
||||
|
||||
return index;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
module.exports = SymSpell;
|
||||
30
backend/node_modules/mnemonist/trie-map.d.ts
generated
vendored
Normal file
30
backend/node_modules/mnemonist/trie-map.d.ts
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Mnemonist TrieMap Typings
|
||||
* ==========================
|
||||
*/
|
||||
export default class TrieMap<K, V> implements Iterable<[K, V]> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(Token?: new () => K);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
set(prefix: K, value: V): this;
|
||||
update(prefix: K, updateFunction: (oldValue: V | undefined) => V): this
|
||||
get(prefix: K): V;
|
||||
delete(prefix: K): boolean;
|
||||
has(prefix: K): boolean;
|
||||
find(prefix: K): Array<[K, V]>;
|
||||
values(): IterableIterator<V>;
|
||||
prefixes(): IterableIterator<K>;
|
||||
keys(): IterableIterator<K>;
|
||||
entries(): IterableIterator<[K, V]>;
|
||||
[Symbol.iterator](): IterableIterator<[K, V]>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I, J>(iterable: Iterable<[I, J]> | {[key: string]: J}): TrieMap<I, J>;
|
||||
}
|
||||
477
backend/node_modules/mnemonist/trie-map.js
generated
vendored
Normal file
477
backend/node_modules/mnemonist/trie-map.js
generated
vendored
Normal file
@@ -0,0 +1,477 @@
|
||||
/**
|
||||
* Mnemonist TrieMap
|
||||
* ==================
|
||||
*
|
||||
* JavaScript TrieMap implementation based upon plain objects. As such this
|
||||
* structure is more a convenience building upon the trie's advantages than
|
||||
* a real performant alternative to already existing structures.
|
||||
*
|
||||
* Note that the Trie is based upon the TrieMap since the underlying machine
|
||||
* is the very same. The Trie just does not let you set values and only
|
||||
* considers the existence of the given prefixes.
|
||||
*/
|
||||
var forEach = require('obliterator/foreach'),
|
||||
Iterator = require('obliterator/iterator');
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
*/
|
||||
var SENTINEL = String.fromCharCode(0);
|
||||
|
||||
/**
|
||||
* TrieMap.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function TrieMap(Token) {
|
||||
this.mode = Token === Array ? 'array' : 'string';
|
||||
this.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the trie.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
TrieMap.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.root = {};
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to set the value of the given prefix in the trie.
|
||||
*
|
||||
* @param {string|array} prefix - Prefix to follow.
|
||||
* @param {any} value - Value for the prefix.
|
||||
* @return {TrieMap}
|
||||
*/
|
||||
TrieMap.prototype.set = function(prefix, value) {
|
||||
var node = this.root,
|
||||
token;
|
||||
|
||||
for (var i = 0, l = prefix.length; i < l; i++) {
|
||||
token = prefix[i];
|
||||
|
||||
node = node[token] || (node[token] = {});
|
||||
}
|
||||
|
||||
// Do we need to increase size?
|
||||
if (!(SENTINEL in node))
|
||||
this.size++;
|
||||
|
||||
node[SENTINEL] = value;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to update the value of the given prefix in the trie.
|
||||
*
|
||||
* @param {string|array} prefix - Prefix to follow.
|
||||
* @param {(oldValue: any | undefined) => any} updateFunction - Update value visitor callback.
|
||||
* @return {TrieMap}
|
||||
*/
|
||||
TrieMap.prototype.update = function(prefix, updateFunction) {
|
||||
var node = this.root,
|
||||
token;
|
||||
|
||||
for (var i = 0, l = prefix.length; i < l; i++) {
|
||||
token = prefix[i];
|
||||
|
||||
node = node[token] || (node[token] = {});
|
||||
}
|
||||
|
||||
// Do we need to increase size?
|
||||
if (!(SENTINEL in node))
|
||||
this.size++;
|
||||
|
||||
node[SENTINEL] = updateFunction(node[SENTINEL]);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to return the value sitting at the end of the given prefix or
|
||||
* undefined if none exist.
|
||||
*
|
||||
* @param {string|array} prefix - Prefix to follow.
|
||||
* @return {any|undefined}
|
||||
*/
|
||||
TrieMap.prototype.get = function(prefix) {
|
||||
var node = this.root,
|
||||
token,
|
||||
i,
|
||||
l;
|
||||
|
||||
for (i = 0, l = prefix.length; i < l; i++) {
|
||||
token = prefix[i];
|
||||
node = node[token];
|
||||
|
||||
// Prefix does not exist
|
||||
if (typeof node === 'undefined')
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(SENTINEL in node))
|
||||
return;
|
||||
|
||||
return node[SENTINEL];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to delete a prefix from the trie.
|
||||
*
|
||||
* @param {string|array} prefix - Prefix to delete.
|
||||
* @return {boolean}
|
||||
*/
|
||||
TrieMap.prototype.delete = function(prefix) {
|
||||
var node = this.root,
|
||||
toPrune = null,
|
||||
tokenToPrune = null,
|
||||
parent,
|
||||
token,
|
||||
i,
|
||||
l;
|
||||
|
||||
for (i = 0, l = prefix.length; i < l; i++) {
|
||||
token = prefix[i];
|
||||
parent = node;
|
||||
node = node[token];
|
||||
|
||||
// Prefix does not exist
|
||||
if (typeof node === 'undefined')
|
||||
return false;
|
||||
|
||||
// Keeping track of a potential branch to prune
|
||||
if (toPrune !== null) {
|
||||
if (Object.keys(node).length > 1) {
|
||||
toPrune = null;
|
||||
tokenToPrune = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (Object.keys(node).length < 2) {
|
||||
toPrune = parent;
|
||||
tokenToPrune = token;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(SENTINEL in node))
|
||||
return false;
|
||||
|
||||
this.size--;
|
||||
|
||||
if (toPrune)
|
||||
delete toPrune[tokenToPrune];
|
||||
else
|
||||
delete node[SENTINEL];
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// TODO: add #.prune?
|
||||
|
||||
/**
|
||||
* Method used to assert whether the given prefix exists in the TrieMap.
|
||||
*
|
||||
* @param {string|array} prefix - Prefix to check.
|
||||
* @return {boolean}
|
||||
*/
|
||||
TrieMap.prototype.has = function(prefix) {
|
||||
var node = this.root,
|
||||
token;
|
||||
|
||||
for (var i = 0, l = prefix.length; i < l; i++) {
|
||||
token = prefix[i];
|
||||
node = node[token];
|
||||
|
||||
if (typeof node === 'undefined')
|
||||
return false;
|
||||
}
|
||||
|
||||
return SENTINEL in node;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to retrieve every item in the trie with the given prefix.
|
||||
*
|
||||
* @param {string|array} prefix - Prefix to query.
|
||||
* @return {array}
|
||||
*/
|
||||
TrieMap.prototype.find = function(prefix) {
|
||||
var isString = typeof prefix === 'string';
|
||||
|
||||
var node = this.root,
|
||||
matches = [],
|
||||
token,
|
||||
i,
|
||||
l;
|
||||
|
||||
for (i = 0, l = prefix.length; i < l; i++) {
|
||||
token = prefix[i];
|
||||
node = node[token];
|
||||
|
||||
if (typeof node === 'undefined')
|
||||
return matches;
|
||||
}
|
||||
|
||||
// Performing DFS from prefix
|
||||
var nodeStack = [node],
|
||||
prefixStack = [prefix],
|
||||
k;
|
||||
|
||||
while (nodeStack.length) {
|
||||
prefix = prefixStack.pop();
|
||||
node = nodeStack.pop();
|
||||
|
||||
for (k in node) {
|
||||
if (k === SENTINEL) {
|
||||
matches.push([prefix, node[SENTINEL]]);
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeStack.push(node[k]);
|
||||
prefixStack.push(isString ? prefix + k : prefix.concat(k));
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the trie's values.
|
||||
*
|
||||
* @param {string|array} [prefix] - Optional starting prefix.
|
||||
* @return {Iterator}
|
||||
*/
|
||||
TrieMap.prototype.values = function(prefix) {
|
||||
var node = this.root,
|
||||
nodeStack = [],
|
||||
token,
|
||||
i,
|
||||
l;
|
||||
|
||||
// Resolving initial prefix
|
||||
if (prefix) {
|
||||
for (i = 0, l = prefix.length; i < l; i++) {
|
||||
token = prefix[i];
|
||||
node = node[token];
|
||||
|
||||
// If the prefix does not exist, we return an empty iterator
|
||||
if (typeof node === 'undefined')
|
||||
return Iterator.empty();
|
||||
}
|
||||
}
|
||||
|
||||
nodeStack.push(node);
|
||||
|
||||
return new Iterator(function() {
|
||||
var currentNode,
|
||||
hasValue = false,
|
||||
k;
|
||||
|
||||
while (nodeStack.length) {
|
||||
currentNode = nodeStack.pop();
|
||||
|
||||
for (k in currentNode) {
|
||||
if (k === SENTINEL) {
|
||||
hasValue = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeStack.push(currentNode[k]);
|
||||
}
|
||||
|
||||
if (hasValue)
|
||||
return {done: false, value: currentNode[SENTINEL]};
|
||||
}
|
||||
|
||||
return {done: true};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the trie's prefixes.
|
||||
*
|
||||
* @param {string|array} [prefix] - Optional starting prefix.
|
||||
* @return {Iterator}
|
||||
*/
|
||||
TrieMap.prototype.prefixes = function(prefix) {
|
||||
var node = this.root,
|
||||
nodeStack = [],
|
||||
prefixStack = [],
|
||||
token,
|
||||
i,
|
||||
l;
|
||||
|
||||
var isString = this.mode === 'string';
|
||||
|
||||
// Resolving initial prefix
|
||||
if (prefix) {
|
||||
for (i = 0, l = prefix.length; i < l; i++) {
|
||||
token = prefix[i];
|
||||
node = node[token];
|
||||
|
||||
// If the prefix does not exist, we return an empty iterator
|
||||
if (typeof node === 'undefined')
|
||||
return Iterator.empty();
|
||||
}
|
||||
}
|
||||
else {
|
||||
prefix = isString ? '' : [];
|
||||
}
|
||||
|
||||
nodeStack.push(node);
|
||||
prefixStack.push(prefix);
|
||||
|
||||
return new Iterator(function() {
|
||||
var currentNode,
|
||||
currentPrefix,
|
||||
hasValue = false,
|
||||
k;
|
||||
|
||||
while (nodeStack.length) {
|
||||
currentNode = nodeStack.pop();
|
||||
currentPrefix = prefixStack.pop();
|
||||
|
||||
for (k in currentNode) {
|
||||
if (k === SENTINEL) {
|
||||
hasValue = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeStack.push(currentNode[k]);
|
||||
prefixStack.push(isString ? currentPrefix + k : currentPrefix.concat(k));
|
||||
}
|
||||
|
||||
if (hasValue)
|
||||
return {done: false, value: currentPrefix};
|
||||
}
|
||||
|
||||
return {done: true};
|
||||
});
|
||||
};
|
||||
TrieMap.prototype.keys = TrieMap.prototype.prefixes;
|
||||
|
||||
/**
|
||||
* Method returning an iterator over the trie's entries.
|
||||
*
|
||||
* @param {string|array} [prefix] - Optional starting prefix.
|
||||
* @return {Iterator}
|
||||
*/
|
||||
TrieMap.prototype.entries = function(prefix) {
|
||||
var node = this.root,
|
||||
nodeStack = [],
|
||||
prefixStack = [],
|
||||
token,
|
||||
i,
|
||||
l;
|
||||
|
||||
var isString = this.mode === 'string';
|
||||
|
||||
// Resolving initial prefix
|
||||
if (prefix) {
|
||||
for (i = 0, l = prefix.length; i < l; i++) {
|
||||
token = prefix[i];
|
||||
node = node[token];
|
||||
|
||||
// If the prefix does not exist, we return an empty iterator
|
||||
if (typeof node === 'undefined')
|
||||
return Iterator.empty();
|
||||
}
|
||||
}
|
||||
else {
|
||||
prefix = isString ? '' : [];
|
||||
}
|
||||
|
||||
nodeStack.push(node);
|
||||
prefixStack.push(prefix);
|
||||
|
||||
return new Iterator(function() {
|
||||
var currentNode,
|
||||
currentPrefix,
|
||||
hasValue = false,
|
||||
k;
|
||||
|
||||
while (nodeStack.length) {
|
||||
currentNode = nodeStack.pop();
|
||||
currentPrefix = prefixStack.pop();
|
||||
|
||||
for (k in currentNode) {
|
||||
if (k === SENTINEL) {
|
||||
hasValue = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeStack.push(currentNode[k]);
|
||||
prefixStack.push(isString ? currentPrefix + k : currentPrefix.concat(k));
|
||||
}
|
||||
|
||||
if (hasValue)
|
||||
return {done: false, value: [currentPrefix, currentNode[SENTINEL]]};
|
||||
}
|
||||
|
||||
return {done: true};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.entries method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
TrieMap.prototype[Symbol.iterator] = TrieMap.prototype.entries;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
TrieMap.prototype.inspect = function() {
|
||||
var proxy = new Array(this.size);
|
||||
|
||||
var iterator = this.entries(),
|
||||
step,
|
||||
i = 0;
|
||||
|
||||
while ((step = iterator.next(), !step.done))
|
||||
proxy[i++] = step.value;
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: TrieMap,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
TrieMap.prototype[Symbol.for('nodejs.util.inspect.custom')] = TrieMap.prototype.inspect;
|
||||
|
||||
TrieMap.prototype.toJSON = function() {
|
||||
return this.root;
|
||||
};
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a trie.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @return {TrieMap}
|
||||
*/
|
||||
TrieMap.from = function(iterable) {
|
||||
var trie = new TrieMap();
|
||||
|
||||
forEach(iterable, function(value, key) {
|
||||
trie.set(key, value);
|
||||
});
|
||||
|
||||
return trie;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
TrieMap.SENTINEL = SENTINEL;
|
||||
module.exports = TrieMap;
|
||||
26
backend/node_modules/mnemonist/trie.d.ts
generated
vendored
Normal file
26
backend/node_modules/mnemonist/trie.d.ts
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Mnemonist Trie Typings
|
||||
* =======================
|
||||
*/
|
||||
export default class Trie<T> implements Iterable<T> {
|
||||
|
||||
// Members
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(Token?: new () => T);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
add(prefix: T): this;
|
||||
delete(prefix: T): boolean;
|
||||
has(prefix: T): boolean;
|
||||
find(prefix: T): Array<T>;
|
||||
prefixes(): IterableIterator<T>;
|
||||
keys(): IterableIterator<T>;
|
||||
[Symbol.iterator](): IterableIterator<T>;
|
||||
inspect(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(iterable: Iterable<I> | {[key: string]: I}): Trie<I>;
|
||||
}
|
||||
167
backend/node_modules/mnemonist/trie.js
generated
vendored
Normal file
167
backend/node_modules/mnemonist/trie.js
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* Mnemonist Trie
|
||||
* ===============
|
||||
*
|
||||
* JavaScript Trie implementation based upon plain objects. As such this
|
||||
* structure is more a convenience building upon the trie's advantages than
|
||||
* a real performant alternative to already existing structures.
|
||||
*
|
||||
* Note that the Trie is based upon the TrieMap since the underlying machine
|
||||
* is the very same. The Trie just does not let you set values and only
|
||||
* considers the existence of the given prefixes.
|
||||
*/
|
||||
var forEach = require('obliterator/foreach'),
|
||||
TrieMap = require('./trie-map.js');
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
*/
|
||||
var SENTINEL = String.fromCharCode(0);
|
||||
|
||||
/**
|
||||
* Trie.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function Trie(Token) {
|
||||
this.mode = Token === Array ? 'array' : 'string';
|
||||
this.clear();
|
||||
}
|
||||
|
||||
// Re-using TrieMap's prototype
|
||||
for (var methodName in TrieMap.prototype)
|
||||
Trie.prototype[methodName] = TrieMap.prototype[methodName];
|
||||
|
||||
// Dropping irrelevant methods
|
||||
delete Trie.prototype.set;
|
||||
delete Trie.prototype.get;
|
||||
delete Trie.prototype.values;
|
||||
delete Trie.prototype.entries;
|
||||
|
||||
/**
|
||||
* Method used to add the given prefix to the trie.
|
||||
*
|
||||
* @param {string|array} prefix - Prefix to follow.
|
||||
* @return {TrieMap}
|
||||
*/
|
||||
Trie.prototype.add = function(prefix) {
|
||||
var node = this.root,
|
||||
token;
|
||||
|
||||
for (var i = 0, l = prefix.length; i < l; i++) {
|
||||
token = prefix[i];
|
||||
|
||||
node = node[token] || (node[token] = {});
|
||||
}
|
||||
|
||||
// Do we need to increase size?
|
||||
if (!(SENTINEL in node))
|
||||
this.size++;
|
||||
|
||||
node[SENTINEL] = true;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to retrieve every item in the trie with the given prefix.
|
||||
*
|
||||
* @param {string|array} prefix - Prefix to query.
|
||||
* @return {array}
|
||||
*/
|
||||
Trie.prototype.find = function(prefix) {
|
||||
var isString = typeof prefix === 'string';
|
||||
|
||||
var node = this.root,
|
||||
matches = [],
|
||||
token,
|
||||
i,
|
||||
l;
|
||||
|
||||
for (i = 0, l = prefix.length; i < l; i++) {
|
||||
token = prefix[i];
|
||||
node = node[token];
|
||||
|
||||
if (typeof node === 'undefined')
|
||||
return matches;
|
||||
}
|
||||
|
||||
// Performing DFS from prefix
|
||||
var nodeStack = [node],
|
||||
prefixStack = [prefix],
|
||||
k;
|
||||
|
||||
while (nodeStack.length) {
|
||||
prefix = prefixStack.pop();
|
||||
node = nodeStack.pop();
|
||||
|
||||
for (k in node) {
|
||||
if (k === SENTINEL) {
|
||||
matches.push(prefix);
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeStack.push(node[k]);
|
||||
prefixStack.push(isString ? prefix + k : prefix.concat(k));
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaching the #.keys method to Symbol.iterator if possible.
|
||||
*/
|
||||
if (typeof Symbol !== 'undefined')
|
||||
Trie.prototype[Symbol.iterator] = Trie.prototype.keys;
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
Trie.prototype.inspect = function() {
|
||||
var proxy = new Set();
|
||||
|
||||
var iterator = this.keys(),
|
||||
step;
|
||||
|
||||
while ((step = iterator.next(), !step.done))
|
||||
proxy.add(step.value);
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: Trie,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
Trie.prototype[Symbol.for('nodejs.util.inspect.custom')] = Trie.prototype.inspect;
|
||||
|
||||
Trie.prototype.toJSON = function() {
|
||||
return this.root;
|
||||
};
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a trie.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @return {Trie}
|
||||
*/
|
||||
Trie.from = function(iterable) {
|
||||
var trie = new Trie();
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
trie.add(value);
|
||||
});
|
||||
|
||||
return trie;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
Trie.SENTINEL = SENTINEL;
|
||||
module.exports = Trie;
|
||||
216
backend/node_modules/mnemonist/utils/binary-search.js
generated
vendored
Normal file
216
backend/node_modules/mnemonist/utils/binary-search.js
generated
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
* Mnemonist Binary Search Helpers
|
||||
* ================================
|
||||
*
|
||||
* Typical binary search functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Function returning the index of the search value in the array or `-1` if
|
||||
* not found.
|
||||
*
|
||||
* @param {array} array - Haystack.
|
||||
* @param {any} value - Needle.
|
||||
* @return {number}
|
||||
*/
|
||||
exports.search = function(array, value, lo, hi) {
|
||||
var mid = 0;
|
||||
|
||||
lo = typeof lo !== 'undefined' ? lo : 0;
|
||||
hi = typeof hi !== 'undefined' ? hi : array.length;
|
||||
|
||||
hi--;
|
||||
|
||||
var current;
|
||||
|
||||
while (lo <= hi) {
|
||||
mid = (lo + hi) >>> 1;
|
||||
|
||||
current = array[mid];
|
||||
|
||||
if (current > value) {
|
||||
hi = ~-mid;
|
||||
}
|
||||
else if (current < value) {
|
||||
lo = -~mid;
|
||||
}
|
||||
else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Same as above, but can use a custom comparator function.
|
||||
*
|
||||
* @param {function} comparator - Custom comparator function.
|
||||
* @param {array} array - Haystack.
|
||||
* @param {any} value - Needle.
|
||||
* @return {number}
|
||||
*/
|
||||
exports.searchWithComparator = function(comparator, array, value) {
|
||||
var mid = 0,
|
||||
lo = 0,
|
||||
hi = ~-array.length,
|
||||
comparison;
|
||||
|
||||
while (lo <= hi) {
|
||||
mid = (lo + hi) >>> 1;
|
||||
|
||||
comparison = comparator(array[mid], value);
|
||||
|
||||
if (comparison > 0) {
|
||||
hi = ~-mid;
|
||||
}
|
||||
else if (comparison < 0) {
|
||||
lo = -~mid;
|
||||
}
|
||||
else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function returning the lower bound of the given value in the array.
|
||||
*
|
||||
* @param {array} array - Haystack.
|
||||
* @param {any} value - Needle.
|
||||
* @param {number} [lo] - Start index.
|
||||
* @param {numner} [hi] - End index.
|
||||
* @return {number}
|
||||
*/
|
||||
exports.lowerBound = function(array, value, lo, hi) {
|
||||
var mid = 0;
|
||||
|
||||
lo = typeof lo !== 'undefined' ? lo : 0;
|
||||
hi = typeof hi !== 'undefined' ? hi : array.length;
|
||||
|
||||
while (lo < hi) {
|
||||
mid = (lo + hi) >>> 1;
|
||||
|
||||
if (value <= array[mid]) {
|
||||
hi = mid;
|
||||
}
|
||||
else {
|
||||
lo = -~mid;
|
||||
}
|
||||
}
|
||||
|
||||
return lo;
|
||||
};
|
||||
|
||||
/**
|
||||
* Same as above, but can use a custom comparator function.
|
||||
*
|
||||
* @param {function} comparator - Custom comparator function.
|
||||
* @param {array} array - Haystack.
|
||||
* @param {any} value - Needle.
|
||||
* @return {number}
|
||||
*/
|
||||
exports.lowerBoundWithComparator = function(comparator, array, value) {
|
||||
var mid = 0,
|
||||
lo = 0,
|
||||
hi = array.length;
|
||||
|
||||
while (lo < hi) {
|
||||
mid = (lo + hi) >>> 1;
|
||||
|
||||
if (comparator(value, array[mid]) <= 0) {
|
||||
hi = mid;
|
||||
}
|
||||
else {
|
||||
lo = -~mid;
|
||||
}
|
||||
}
|
||||
|
||||
return lo;
|
||||
};
|
||||
|
||||
/**
|
||||
* Same as above, but can work on sorted indices.
|
||||
*
|
||||
* @param {array} array - Haystack.
|
||||
* @param {array} array - Indices.
|
||||
* @param {any} value - Needle.
|
||||
* @return {number}
|
||||
*/
|
||||
exports.lowerBoundIndices = function(array, indices, value, lo, hi) {
|
||||
var mid = 0;
|
||||
|
||||
lo = typeof lo !== 'undefined' ? lo : 0;
|
||||
hi = typeof hi !== 'undefined' ? hi : array.length;
|
||||
|
||||
while (lo < hi) {
|
||||
mid = (lo + hi) >>> 1;
|
||||
|
||||
if (value <= array[indices[mid]]) {
|
||||
hi = mid;
|
||||
}
|
||||
else {
|
||||
lo = -~mid;
|
||||
}
|
||||
}
|
||||
|
||||
return lo;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function returning the upper bound of the given value in the array.
|
||||
*
|
||||
* @param {array} array - Haystack.
|
||||
* @param {any} value - Needle.
|
||||
* @param {number} [lo] - Start index.
|
||||
* @param {numner} [hi] - End index.
|
||||
* @return {number}
|
||||
*/
|
||||
exports.upperBound = function(array, value, lo, hi) {
|
||||
var mid = 0;
|
||||
|
||||
lo = typeof lo !== 'undefined' ? lo : 0;
|
||||
hi = typeof hi !== 'undefined' ? hi : array.length;
|
||||
|
||||
while (lo < hi) {
|
||||
mid = (lo + hi) >>> 1;
|
||||
|
||||
if (value >= array[mid]) {
|
||||
lo = -~mid;
|
||||
}
|
||||
else {
|
||||
hi = mid;
|
||||
}
|
||||
}
|
||||
|
||||
return lo;
|
||||
};
|
||||
|
||||
/**
|
||||
* Same as above, but can use a custom comparator function.
|
||||
*
|
||||
* @param {function} comparator - Custom comparator function.
|
||||
* @param {array} array - Haystack.
|
||||
* @param {any} value - Needle.
|
||||
* @return {number}
|
||||
*/
|
||||
exports.upperBoundWithComparator = function(comparator, array, value) {
|
||||
var mid = 0,
|
||||
lo = 0,
|
||||
hi = array.length;
|
||||
|
||||
while (lo < hi) {
|
||||
mid = (lo + hi) >>> 1;
|
||||
|
||||
if (comparator(value, array[mid]) >= 0) {
|
||||
lo = -~mid;
|
||||
}
|
||||
else {
|
||||
hi = mid;
|
||||
}
|
||||
}
|
||||
|
||||
return lo;
|
||||
};
|
||||
109
backend/node_modules/mnemonist/utils/bitwise.js
generated
vendored
Normal file
109
backend/node_modules/mnemonist/utils/bitwise.js
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Mnemonist Bitwise Helpers
|
||||
* ==========================
|
||||
*
|
||||
* Miscellaneous helpers helping with bitwise operations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Takes a 32 bits integer and returns its MSB using SWAR strategy.
|
||||
*
|
||||
* @param {number} x - Target number.
|
||||
* @return {number}
|
||||
*/
|
||||
function msb32(x) {
|
||||
x |= (x >> 1);
|
||||
x |= (x >> 2);
|
||||
x |= (x >> 4);
|
||||
x |= (x >> 8);
|
||||
x |= (x >> 16);
|
||||
|
||||
return (x & ~(x >> 1));
|
||||
}
|
||||
exports.msb32 = msb32;
|
||||
|
||||
/**
|
||||
* Takes a byte and returns its MSB using SWAR strategy.
|
||||
*
|
||||
* @param {number} x - Target number.
|
||||
* @return {number}
|
||||
*/
|
||||
function msb8(x) {
|
||||
x |= (x >> 1);
|
||||
x |= (x >> 2);
|
||||
x |= (x >> 4);
|
||||
|
||||
return (x & ~(x >> 1));
|
||||
}
|
||||
exports.msb8 = msb8;
|
||||
|
||||
/**
|
||||
* Takes a number and return bit at position.
|
||||
*
|
||||
* @param {number} x - Target number.
|
||||
* @param {number} pos - Position.
|
||||
* @return {number}
|
||||
*/
|
||||
exports.test = function(x, pos) {
|
||||
return (x >> pos) & 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compare two bytes and return their critical bit.
|
||||
*
|
||||
* @param {number} a - First byte.
|
||||
* @param {number} b - Second byte.
|
||||
* @return {number}
|
||||
*/
|
||||
exports.criticalBit8 = function(a, b) {
|
||||
return msb8(a ^ b);
|
||||
};
|
||||
|
||||
exports.criticalBit8Mask = function(a, b) {
|
||||
return (~msb8(a ^ b) >>> 0) & 0xff;
|
||||
};
|
||||
|
||||
exports.testCriticalBit8 = function(x, mask) {
|
||||
return (1 + (x | mask)) >> 8;
|
||||
};
|
||||
|
||||
exports.criticalBit32Mask = function(a, b) {
|
||||
return (~msb32(a ^ b) >>> 0) & 0xffffffff;
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes a 32 bits integer and returns its population count (number of 1 of
|
||||
* the binary representation).
|
||||
*
|
||||
* @param {number} x - Target number.
|
||||
* @return {number}
|
||||
*/
|
||||
exports.popcount = function(x) {
|
||||
x -= x >> 1 & 0x55555555;
|
||||
x = (x & 0x33333333) + (x >> 2 & 0x33333333);
|
||||
x = x + (x >> 4) & 0x0f0f0f0f;
|
||||
x += x >> 8;
|
||||
x += x >> 16;
|
||||
return x & 0x7f;
|
||||
};
|
||||
|
||||
/**
|
||||
* Slightly faster popcount function based on a precomputed table of 8bits
|
||||
* words.
|
||||
*
|
||||
* @param {number} x - Target number.
|
||||
* @return {number}
|
||||
*/
|
||||
var TABLE8 = new Uint8Array(Math.pow(2, 8));
|
||||
|
||||
for (var i = 0, l = TABLE8.length; i < l; i++)
|
||||
TABLE8[i] = exports.popcount(i);
|
||||
|
||||
exports.table8Popcount = function(x) {
|
||||
return (
|
||||
TABLE8[x & 0xff] +
|
||||
TABLE8[(x >> 8) & 0xff] +
|
||||
TABLE8[(x >> 16) & 0xff] +
|
||||
TABLE8[(x >> 24) & 0xff]
|
||||
);
|
||||
};
|
||||
79
backend/node_modules/mnemonist/utils/comparators.js
generated
vendored
Normal file
79
backend/node_modules/mnemonist/utils/comparators.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Mnemonist Heap Comparators
|
||||
* ===========================
|
||||
*
|
||||
* Default comparators & functions dealing with comparators reversing etc.
|
||||
*/
|
||||
var DEFAULT_COMPARATOR = function(a, b) {
|
||||
if (a < b)
|
||||
return -1;
|
||||
if (a > b)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
var DEFAULT_REVERSE_COMPARATOR = function(a, b) {
|
||||
if (a < b)
|
||||
return 1;
|
||||
if (a > b)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function used to reverse a comparator.
|
||||
*/
|
||||
function reverseComparator(comparator) {
|
||||
return function(a, b) {
|
||||
return comparator(b, a);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Function returning a tuple comparator.
|
||||
*/
|
||||
function createTupleComparator(size) {
|
||||
if (size === 2) {
|
||||
return function(a, b) {
|
||||
if (a[0] < b[0])
|
||||
return -1;
|
||||
|
||||
if (a[0] > b[0])
|
||||
return 1;
|
||||
|
||||
if (a[1] < b[1])
|
||||
return -1;
|
||||
|
||||
if (a[1] > b[1])
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
return function(a, b) {
|
||||
var i = 0;
|
||||
|
||||
while (i < size) {
|
||||
if (a[i] < b[i])
|
||||
return -1;
|
||||
|
||||
if (a[i] > b[i])
|
||||
return 1;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
exports.DEFAULT_COMPARATOR = DEFAULT_COMPARATOR;
|
||||
exports.DEFAULT_REVERSE_COMPARATOR = DEFAULT_REVERSE_COMPARATOR;
|
||||
exports.reverseComparator = reverseComparator;
|
||||
exports.createTupleComparator = createTupleComparator;
|
||||
107
backend/node_modules/mnemonist/utils/hash-tables.js
generated
vendored
Normal file
107
backend/node_modules/mnemonist/utils/hash-tables.js
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
/* eslint no-constant-condition: 0 */
|
||||
/**
|
||||
* Mnemonist Hashtable Helpers
|
||||
* ============================
|
||||
*
|
||||
* Miscellaneous helpers helper function dealing with hashtables.
|
||||
*/
|
||||
function jenkinsInt32(a) {
|
||||
|
||||
a = (a + 0x7ed55d16) + (a << 12);
|
||||
a = (a ^ 0xc761c23c) ^ (a >> 19);
|
||||
a = (a + 0x165667b1) + (a << 5);
|
||||
a = (a + 0xd3a2646c) ^ (a << 9);
|
||||
a = (a + 0xfd7046c5) + (a << 3);
|
||||
a = (a ^ 0xb55a4f09) ^ (a >> 16);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
function linearProbingGet(hash, keys, values, key) {
|
||||
var n = keys.length,
|
||||
j = hash(key) & (n - 1),
|
||||
i = j;
|
||||
|
||||
var c;
|
||||
|
||||
while (true) {
|
||||
c = keys[i];
|
||||
|
||||
if (c === key)
|
||||
return values[i];
|
||||
|
||||
else if (c === 0)
|
||||
return;
|
||||
|
||||
// Handling wrapping around
|
||||
i += 1;
|
||||
i %= n;
|
||||
|
||||
// Full turn
|
||||
if (i === j)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function linearProbingHas(hash, keys, key) {
|
||||
var n = keys.length,
|
||||
j = hash(key) & (n - 1),
|
||||
i = j;
|
||||
|
||||
var c;
|
||||
|
||||
while (true) {
|
||||
c = keys[i];
|
||||
|
||||
if (c === key)
|
||||
return true;
|
||||
|
||||
else if (c === 0)
|
||||
return false;
|
||||
|
||||
// Handling wrapping around
|
||||
i += 1;
|
||||
i %= n;
|
||||
|
||||
// Full turn
|
||||
if (i === j)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function linearProbingSet(hash, keys, values, key, value) {
|
||||
var n = keys.length,
|
||||
j = hash(key) & (n - 1),
|
||||
i = j;
|
||||
|
||||
var c;
|
||||
|
||||
while (true) {
|
||||
c = keys[i];
|
||||
|
||||
if (c === 0 || c === key)
|
||||
break;
|
||||
|
||||
// Handling wrapping around
|
||||
i += 1;
|
||||
i %= n;
|
||||
|
||||
// Full turn
|
||||
if (i === j)
|
||||
throw new Error('mnemonist/utils/hash-tables.linearProbingSet: table is full.');
|
||||
}
|
||||
|
||||
keys[i] = key;
|
||||
values[i] = value;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
hashes: {
|
||||
jenkinsInt32: jenkinsInt32
|
||||
},
|
||||
linearProbing: {
|
||||
get: linearProbingGet,
|
||||
has: linearProbingHas,
|
||||
set: linearProbingSet
|
||||
}
|
||||
};
|
||||
93
backend/node_modules/mnemonist/utils/iterables.js
generated
vendored
Normal file
93
backend/node_modules/mnemonist/utils/iterables.js
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Mnemonist Iterable Function
|
||||
* ============================
|
||||
*
|
||||
* Harmonized iteration helpers over mixed iterable targets.
|
||||
*/
|
||||
var forEach = require('obliterator/foreach');
|
||||
|
||||
var typed = require('./typed-arrays.js');
|
||||
|
||||
/**
|
||||
* Function used to determine whether the given object supports array-like
|
||||
* random access.
|
||||
*
|
||||
* @param {any} target - Target object.
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isArrayLike(target) {
|
||||
return Array.isArray(target) || typed.isTypedArray(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to guess the length of the structure over which we are going
|
||||
* to iterate.
|
||||
*
|
||||
* @param {any} target - Target object.
|
||||
* @return {number|undefined}
|
||||
*/
|
||||
function guessLength(target) {
|
||||
if (typeof target.length === 'number')
|
||||
return target.length;
|
||||
|
||||
if (typeof target.size === 'number')
|
||||
return target.size;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to convert an iterable to an array.
|
||||
*
|
||||
* @param {any} target - Iteration target.
|
||||
* @return {array}
|
||||
*/
|
||||
function toArray(target) {
|
||||
var l = guessLength(target);
|
||||
|
||||
var array = typeof l === 'number' ? new Array(l) : [];
|
||||
|
||||
var i = 0;
|
||||
|
||||
// TODO: we could optimize when given target is array like
|
||||
forEach(target, function(value) {
|
||||
array[i++] = value;
|
||||
});
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as above but returns a supplementary indices array.
|
||||
*
|
||||
* @param {any} target - Iteration target.
|
||||
* @return {array}
|
||||
*/
|
||||
function toArrayWithIndices(target) {
|
||||
var l = guessLength(target);
|
||||
|
||||
var IndexArray = typeof l === 'number' ?
|
||||
typed.getPointerArray(l) :
|
||||
Array;
|
||||
|
||||
var array = typeof l === 'number' ? new Array(l) : [];
|
||||
var indices = typeof l === 'number' ? new IndexArray(l) : [];
|
||||
|
||||
var i = 0;
|
||||
|
||||
// TODO: we could optimize when given target is array like
|
||||
forEach(target, function(value) {
|
||||
array[i] = value;
|
||||
indices[i] = i++;
|
||||
});
|
||||
|
||||
return [array, indices];
|
||||
}
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
exports.isArrayLike = isArrayLike;
|
||||
exports.guessLength = guessLength;
|
||||
exports.toArray = toArray;
|
||||
exports.toArrayWithIndices = toArrayWithIndices;
|
||||
563
backend/node_modules/mnemonist/utils/merge.js
generated
vendored
Normal file
563
backend/node_modules/mnemonist/utils/merge.js
generated
vendored
Normal file
@@ -0,0 +1,563 @@
|
||||
/* eslint no-constant-condition: 0 */
|
||||
/**
|
||||
* Mnemonist Merge Helpers
|
||||
* ========================
|
||||
*
|
||||
* Various merge algorithms used to handle sorted lists. Note that the given
|
||||
* functions are optimized and won't accept mixed arguments.
|
||||
*
|
||||
* Note: maybe this piece of code belong to sortilege, along with binary-search.
|
||||
*/
|
||||
var typed = require('./typed-arrays.js'),
|
||||
isArrayLike = require('./iterables.js').isArrayLike,
|
||||
binarySearch = require('./binary-search.js'),
|
||||
FibonacciHeap = require('../fibonacci-heap.js');
|
||||
|
||||
// TODO: update to use exponential search
|
||||
// TODO: when not knowing final length => should use plain arrays rather than
|
||||
// same type as input
|
||||
|
||||
/**
|
||||
* Merge two sorted array-like structures into one.
|
||||
*
|
||||
* @param {array} a - First array.
|
||||
* @param {array} b - Second array.
|
||||
* @return {array}
|
||||
*/
|
||||
function mergeArrays(a, b) {
|
||||
|
||||
// One of the arrays is empty
|
||||
if (a.length === 0)
|
||||
return b.slice();
|
||||
if (b.length === 0)
|
||||
return a.slice();
|
||||
|
||||
// Finding min array
|
||||
var tmp;
|
||||
|
||||
if (a[0] > b[0]) {
|
||||
tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
// If array have non overlapping ranges, we can just concatenate them
|
||||
var aEnd = a[a.length - 1],
|
||||
bStart = b[0];
|
||||
|
||||
if (aEnd <= bStart) {
|
||||
if (typed.isTypedArray(a))
|
||||
return typed.concat(a, b);
|
||||
return a.concat(b);
|
||||
}
|
||||
|
||||
// Initializing target
|
||||
var array = new a.constructor(a.length + b.length);
|
||||
|
||||
// Iterating until we overlap
|
||||
var i, l, v;
|
||||
|
||||
for (i = 0, l = a.length; i < l; i++) {
|
||||
v = a[i];
|
||||
|
||||
if (v <= bStart)
|
||||
array[i] = v;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// Handling overlap
|
||||
var aPointer = i,
|
||||
aLength = a.length,
|
||||
bPointer = 0,
|
||||
bLength = b.length,
|
||||
aHead,
|
||||
bHead;
|
||||
|
||||
while (aPointer < aLength && bPointer < bLength) {
|
||||
aHead = a[aPointer];
|
||||
bHead = b[bPointer];
|
||||
|
||||
if (aHead <= bHead) {
|
||||
array[i++] = aHead;
|
||||
aPointer++;
|
||||
}
|
||||
else {
|
||||
array[i++] = bHead;
|
||||
bPointer++;
|
||||
}
|
||||
}
|
||||
|
||||
// Filling
|
||||
while (aPointer < aLength)
|
||||
array[i++] = a[aPointer++];
|
||||
while (bPointer < bLength)
|
||||
array[i++] = b[bPointer++];
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the union of two already unique sorted array-like structures into one.
|
||||
*
|
||||
* @param {array} a - First array.
|
||||
* @param {array} b - Second array.
|
||||
* @return {array}
|
||||
*/
|
||||
function unionUniqueArrays(a, b) {
|
||||
|
||||
// One of the arrays is empty
|
||||
if (a.length === 0)
|
||||
return b.slice();
|
||||
if (b.length === 0)
|
||||
return a.slice();
|
||||
|
||||
// Finding min array
|
||||
var tmp;
|
||||
|
||||
if (a[0] > b[0]) {
|
||||
tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
// If array have non overlapping ranges, we can just concatenate them
|
||||
var aEnd = a[a.length - 1],
|
||||
bStart = b[0];
|
||||
|
||||
if (aEnd < bStart) {
|
||||
if (typed.isTypedArray(a))
|
||||
return typed.concat(a, b);
|
||||
return a.concat(b);
|
||||
}
|
||||
|
||||
// Initializing target
|
||||
var array = new a.constructor();
|
||||
|
||||
// Iterating until we overlap
|
||||
var i, l, v;
|
||||
|
||||
for (i = 0, l = a.length; i < l; i++) {
|
||||
v = a[i];
|
||||
|
||||
if (v < bStart)
|
||||
array.push(v);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// Handling overlap
|
||||
var aPointer = i,
|
||||
aLength = a.length,
|
||||
bPointer = 0,
|
||||
bLength = b.length,
|
||||
aHead,
|
||||
bHead;
|
||||
|
||||
while (aPointer < aLength && bPointer < bLength) {
|
||||
aHead = a[aPointer];
|
||||
bHead = b[bPointer];
|
||||
|
||||
if (aHead <= bHead) {
|
||||
|
||||
if (array.length === 0 || array[array.length - 1] !== aHead)
|
||||
array.push(aHead);
|
||||
|
||||
aPointer++;
|
||||
}
|
||||
else {
|
||||
if (array.length === 0 || array[array.length - 1] !== bHead)
|
||||
array.push(bHead);
|
||||
|
||||
bPointer++;
|
||||
}
|
||||
}
|
||||
|
||||
// Filling
|
||||
// TODO: it's possible to optimize a bit here, since the condition is only
|
||||
// relevant the first time
|
||||
while (aPointer < aLength) {
|
||||
aHead = a[aPointer++];
|
||||
|
||||
if (array.length === 0 || array[array.length - 1] !== aHead)
|
||||
array.push(aHead);
|
||||
}
|
||||
while (bPointer < bLength) {
|
||||
bHead = b[bPointer++];
|
||||
|
||||
if (array.length === 0 || array[array.length - 1] !== bHead)
|
||||
array.push(bHead);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the intersection of two already unique sorted array-like structures into one.
|
||||
*
|
||||
* @param {array} a - First array.
|
||||
* @param {array} b - Second array.
|
||||
* @return {array}
|
||||
*/
|
||||
exports.intersectionUniqueArrays = function(a, b) {
|
||||
|
||||
// One of the arrays is empty
|
||||
if (a.length === 0 || b.length === 0)
|
||||
return new a.constructor(0);
|
||||
|
||||
// Finding min array
|
||||
var tmp;
|
||||
|
||||
if (a[0] > b[0]) {
|
||||
tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
// If array have non overlapping ranges, there is no intersection
|
||||
var aEnd = a[a.length - 1],
|
||||
bStart = b[0];
|
||||
|
||||
if (aEnd < bStart)
|
||||
return new a.constructor(0);
|
||||
|
||||
// Initializing target
|
||||
var array = new a.constructor();
|
||||
|
||||
// Handling overlap
|
||||
var aPointer = binarySearch.lowerBound(a, bStart),
|
||||
aLength = a.length,
|
||||
bPointer = 0,
|
||||
bLength = binarySearch.upperBound(b, aEnd),
|
||||
aHead,
|
||||
bHead;
|
||||
|
||||
while (aPointer < aLength && bPointer < bLength) {
|
||||
aHead = a[aPointer];
|
||||
bHead = b[bPointer];
|
||||
|
||||
if (aHead < bHead) {
|
||||
aPointer = binarySearch.lowerBound(a, bHead, aPointer + 1);
|
||||
}
|
||||
else if (aHead > bHead) {
|
||||
bPointer = binarySearch.lowerBound(b, aHead, bPointer + 1);
|
||||
}
|
||||
else {
|
||||
array.push(aHead);
|
||||
aPointer++;
|
||||
bPointer++;
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
/**
|
||||
* Merge k sorted array-like structures into one.
|
||||
*
|
||||
* @param {array<array>} arrays - Arrays to merge.
|
||||
* @return {array}
|
||||
*/
|
||||
function kWayMergeArrays(arrays) {
|
||||
var length = 0,
|
||||
max = -Infinity,
|
||||
al,
|
||||
i,
|
||||
l;
|
||||
|
||||
var filtered = [];
|
||||
|
||||
for (i = 0, l = arrays.length; i < l; i++) {
|
||||
al = arrays[i].length;
|
||||
|
||||
if (al === 0)
|
||||
continue;
|
||||
|
||||
filtered.push(arrays[i]);
|
||||
|
||||
length += al;
|
||||
|
||||
if (al > max)
|
||||
max = al;
|
||||
}
|
||||
|
||||
if (filtered.length === 0)
|
||||
return new arrays[0].constructor(0);
|
||||
|
||||
if (filtered.length === 1)
|
||||
return filtered[0].slice();
|
||||
|
||||
if (filtered.length === 2)
|
||||
return mergeArrays(filtered[0], filtered[1]);
|
||||
|
||||
arrays = filtered;
|
||||
|
||||
var array = new arrays[0].constructor(length);
|
||||
|
||||
var PointerArray = typed.getPointerArray(max);
|
||||
|
||||
var pointers = new PointerArray(arrays.length);
|
||||
|
||||
// TODO: benchmark vs. a binomial heap
|
||||
var heap = new FibonacciHeap(function(a, b) {
|
||||
a = arrays[a][pointers[a]];
|
||||
b = arrays[b][pointers[b]];
|
||||
|
||||
if (a < b)
|
||||
return -1;
|
||||
|
||||
if (a > b)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
for (i = 0; i < l; i++)
|
||||
heap.push(i);
|
||||
|
||||
i = 0;
|
||||
|
||||
var p,
|
||||
v;
|
||||
|
||||
while (heap.size) {
|
||||
p = heap.pop();
|
||||
v = arrays[p][pointers[p]++];
|
||||
array[i++] = v;
|
||||
|
||||
if (pointers[p] < arrays[p].length)
|
||||
heap.push(p);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the union of k sorted unique array-like structures into one.
|
||||
*
|
||||
* @param {array<array>} arrays - Arrays to merge.
|
||||
* @return {array}
|
||||
*/
|
||||
function kWayUnionUniqueArrays(arrays) {
|
||||
var max = -Infinity,
|
||||
al,
|
||||
i,
|
||||
l;
|
||||
|
||||
var filtered = [];
|
||||
|
||||
for (i = 0, l = arrays.length; i < l; i++) {
|
||||
al = arrays[i].length;
|
||||
|
||||
if (al === 0)
|
||||
continue;
|
||||
|
||||
filtered.push(arrays[i]);
|
||||
|
||||
if (al > max)
|
||||
max = al;
|
||||
}
|
||||
|
||||
if (filtered.length === 0)
|
||||
return new arrays[0].constructor(0);
|
||||
|
||||
if (filtered.length === 1)
|
||||
return filtered[0].slice();
|
||||
|
||||
if (filtered.length === 2)
|
||||
return unionUniqueArrays(filtered[0], filtered[1]);
|
||||
|
||||
arrays = filtered;
|
||||
|
||||
var array = new arrays[0].constructor();
|
||||
|
||||
var PointerArray = typed.getPointerArray(max);
|
||||
|
||||
var pointers = new PointerArray(arrays.length);
|
||||
|
||||
// TODO: benchmark vs. a binomial heap
|
||||
var heap = new FibonacciHeap(function(a, b) {
|
||||
a = arrays[a][pointers[a]];
|
||||
b = arrays[b][pointers[b]];
|
||||
|
||||
if (a < b)
|
||||
return -1;
|
||||
|
||||
if (a > b)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
for (i = 0; i < l; i++)
|
||||
heap.push(i);
|
||||
|
||||
var p,
|
||||
v;
|
||||
|
||||
while (heap.size) {
|
||||
p = heap.pop();
|
||||
v = arrays[p][pointers[p]++];
|
||||
|
||||
if (array.length === 0 || array[array.length - 1] !== v)
|
||||
array.push(v);
|
||||
|
||||
if (pointers[p] < arrays[p].length)
|
||||
heap.push(p);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the intersection of k sorted array-like structures into one.
|
||||
*
|
||||
* @param {array<array>} arrays - Arrays to merge.
|
||||
* @return {array}
|
||||
*/
|
||||
exports.kWayIntersectionUniqueArrays = function(arrays) {
|
||||
var max = -Infinity,
|
||||
maxStart = -Infinity,
|
||||
minEnd = Infinity,
|
||||
first,
|
||||
last,
|
||||
al,
|
||||
i,
|
||||
l;
|
||||
|
||||
for (i = 0, l = arrays.length; i < l; i++) {
|
||||
al = arrays[i].length;
|
||||
|
||||
// If one of the arrays is empty, so is the intersection
|
||||
if (al === 0)
|
||||
return [];
|
||||
|
||||
if (al > max)
|
||||
max = al;
|
||||
|
||||
first = arrays[i][0];
|
||||
last = arrays[i][al - 1];
|
||||
|
||||
if (first > maxStart)
|
||||
maxStart = first;
|
||||
|
||||
if (last < minEnd)
|
||||
minEnd = last;
|
||||
}
|
||||
|
||||
// Full overlap is impossible
|
||||
if (maxStart > minEnd)
|
||||
return [];
|
||||
|
||||
// Only one value
|
||||
if (maxStart === minEnd)
|
||||
return [maxStart];
|
||||
|
||||
// NOTE: trying to outsmart I(D,I(C,I(A,B))) is pointless unfortunately...
|
||||
// NOTE: I tried to be very clever about bounds but it does not seem
|
||||
// to improve the performance of the algorithm.
|
||||
var a, b,
|
||||
array = arrays[0],
|
||||
aPointer,
|
||||
bPointer,
|
||||
aLimit,
|
||||
bLimit,
|
||||
aHead,
|
||||
bHead,
|
||||
start = maxStart;
|
||||
|
||||
for (i = 1; i < l; i++) {
|
||||
a = array;
|
||||
b = arrays[i];
|
||||
|
||||
// Change that to `[]` and observe some perf drops on V8...
|
||||
array = new Array();
|
||||
|
||||
aPointer = 0;
|
||||
bPointer = binarySearch.lowerBound(b, start);
|
||||
|
||||
aLimit = a.length;
|
||||
bLimit = b.length;
|
||||
|
||||
while (aPointer < aLimit && bPointer < bLimit) {
|
||||
aHead = a[aPointer];
|
||||
bHead = b[bPointer];
|
||||
|
||||
if (aHead < bHead) {
|
||||
aPointer = binarySearch.lowerBound(a, bHead, aPointer + 1);
|
||||
}
|
||||
else if (aHead > bHead) {
|
||||
bPointer = binarySearch.lowerBound(b, aHead, bPointer + 1);
|
||||
}
|
||||
else {
|
||||
array.push(aHead);
|
||||
aPointer++;
|
||||
bPointer++;
|
||||
}
|
||||
}
|
||||
|
||||
if (array.length === 0)
|
||||
return array;
|
||||
|
||||
start = array[0];
|
||||
}
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
/**
|
||||
* Variadic merging all of the given arrays.
|
||||
*
|
||||
* @param {...array}
|
||||
* @return {array}
|
||||
*/
|
||||
exports.merge = function() {
|
||||
if (arguments.length === 2) {
|
||||
if (isArrayLike(arguments[0]))
|
||||
return mergeArrays(arguments[0], arguments[1]);
|
||||
}
|
||||
else {
|
||||
if (isArrayLike(arguments[0]))
|
||||
return kWayMergeArrays(arguments);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Variadic function performing the union of all the given unique arrays.
|
||||
*
|
||||
* @param {...array}
|
||||
* @return {array}
|
||||
*/
|
||||
exports.unionUnique = function() {
|
||||
if (arguments.length === 2) {
|
||||
if (isArrayLike(arguments[0]))
|
||||
return unionUniqueArrays(arguments[0], arguments[1]);
|
||||
}
|
||||
else {
|
||||
if (isArrayLike(arguments[0]))
|
||||
return kWayUnionUniqueArrays(arguments);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Variadic function performing the intersection of all the given unique arrays.
|
||||
*
|
||||
* @param {...array}
|
||||
* @return {array}
|
||||
*/
|
||||
exports.intersectionUnique = function() {
|
||||
if (arguments.length === 2) {
|
||||
if (isArrayLike(arguments[0]))
|
||||
return exports.intersectionUniqueArrays(arguments[0], arguments[1]);
|
||||
}
|
||||
else {
|
||||
if (isArrayLike(arguments[0]))
|
||||
return exports.kWayIntersectionUniqueArrays(arguments);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
87
backend/node_modules/mnemonist/utils/murmurhash3.js
generated
vendored
Normal file
87
backend/node_modules/mnemonist/utils/murmurhash3.js
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
/* eslint no-fallthrough: 0 */
|
||||
/**
|
||||
* Mnemonist MurmurHash 3
|
||||
* =======================
|
||||
*
|
||||
* Straightforward implementation of the third version of MurmurHash.
|
||||
*
|
||||
* Note: this piece of code belong to haschisch.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Various helpers.
|
||||
*/
|
||||
function mul32(a, b) {
|
||||
return (a & 0xffff) * b + (((a >>> 16) * b & 0xffff) << 16) & 0xffffffff;
|
||||
}
|
||||
|
||||
function sum32(a, b) {
|
||||
return (a & 0xffff) + (b >>> 16) + (((a >>> 16) + b & 0xffff) << 16) & 0xffffffff;
|
||||
}
|
||||
|
||||
function rotl32(a, b) {
|
||||
return (a << b) | (a >>> (32 - b));
|
||||
}
|
||||
|
||||
/**
|
||||
* MumurHash3 function.
|
||||
*
|
||||
* @param {number} seed - Seed.
|
||||
* @param {ByteArray} data - Data.
|
||||
*/
|
||||
module.exports = function murmurhash3(seed, data) {
|
||||
var c1 = 0xcc9e2d51,
|
||||
c2 = 0x1b873593,
|
||||
r1 = 15,
|
||||
r2 = 13,
|
||||
m = 5,
|
||||
n = 0x6b64e654;
|
||||
|
||||
var hash = seed,
|
||||
k1,
|
||||
i,
|
||||
l;
|
||||
|
||||
for (i = 0, l = data.length - 4; i <= l; i += 4) {
|
||||
k1 = (
|
||||
data[i] |
|
||||
(data[i + 1] << 8) |
|
||||
(data[i + 2] << 16) |
|
||||
(data[i + 3] << 24)
|
||||
);
|
||||
|
||||
k1 = mul32(k1, c1);
|
||||
k1 = rotl32(k1, r1);
|
||||
k1 = mul32(k1, c2);
|
||||
|
||||
hash ^= k1;
|
||||
hash = rotl32(hash, r2);
|
||||
hash = mul32(hash, m);
|
||||
hash = sum32(hash, n);
|
||||
}
|
||||
|
||||
k1 = 0;
|
||||
|
||||
switch (data.length & 3) {
|
||||
case 3:
|
||||
k1 ^= data[i + 2] << 16;
|
||||
case 2:
|
||||
k1 ^= data[i + 1] << 8;
|
||||
case 1:
|
||||
k1 ^= data[i];
|
||||
k1 = mul32(k1, c1);
|
||||
k1 = rotl32(k1, r1);
|
||||
k1 = mul32(k1, c2);
|
||||
hash ^= k1;
|
||||
default:
|
||||
}
|
||||
|
||||
hash ^= data.length;
|
||||
hash ^= hash >>> 16;
|
||||
hash = mul32(hash, 0x85ebca6b);
|
||||
hash ^= hash >>> 13;
|
||||
hash = mul32(hash, 0xc2b2ae35);
|
||||
hash ^= hash >>> 16;
|
||||
|
||||
return hash >>> 0;
|
||||
};
|
||||
10
backend/node_modules/mnemonist/utils/typed-arrays.d.ts
generated
vendored
Normal file
10
backend/node_modules/mnemonist/utils/typed-arrays.d.ts
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
export type PointerArray = Uint8Array | Uint16Array | Uint32Array | Float64Array;
|
||||
export type SignedPointerArray = Int8Array | Int16Array | Int32Array | Float64Array;
|
||||
export type PointerArrayConstructor = Uint8ArrayConstructor | Uint16ArrayConstructor | Uint32ArrayConstructor | Float64ArrayConstructor;
|
||||
export type SignedPointerArrayConstructor = Int8ArrayConstructor | Int16ArrayConstructor | Int32ArrayConstructor | Float64ArrayConstructor;
|
||||
|
||||
export function getPointerArray(size: number): PointerArrayConstructor;
|
||||
export function getSignedPointerArray(size: number): SignedPointerArrayConstructor;
|
||||
export function getNumberType(value: number): PointerArrayConstructor | SignedPointerArrayConstructor;
|
||||
export function isTypedArray(value: unknown): boolean;
|
||||
export function indices(length: number): PointerArray;
|
||||
187
backend/node_modules/mnemonist/utils/typed-arrays.js
generated
vendored
Normal file
187
backend/node_modules/mnemonist/utils/typed-arrays.js
generated
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
/**
|
||||
* Mnemonist Typed Array Helpers
|
||||
* ==============================
|
||||
*
|
||||
* Miscellaneous helpers related to typed arrays.
|
||||
*/
|
||||
|
||||
/**
|
||||
* When using an unsigned integer array to store pointers, one might want to
|
||||
* choose the optimal word size in regards to the actual numbers of pointers
|
||||
* to store.
|
||||
*
|
||||
* This helpers does just that.
|
||||
*
|
||||
* @param {number} size - Expected size of the array to map.
|
||||
* @return {TypedArray}
|
||||
*/
|
||||
var MAX_8BIT_INTEGER = Math.pow(2, 8) - 1,
|
||||
MAX_16BIT_INTEGER = Math.pow(2, 16) - 1,
|
||||
MAX_32BIT_INTEGER = Math.pow(2, 32) - 1;
|
||||
|
||||
var MAX_SIGNED_8BIT_INTEGER = Math.pow(2, 7) - 1,
|
||||
MAX_SIGNED_16BIT_INTEGER = Math.pow(2, 15) - 1,
|
||||
MAX_SIGNED_32BIT_INTEGER = Math.pow(2, 31) - 1;
|
||||
|
||||
exports.getPointerArray = function(size) {
|
||||
var maxIndex = size - 1;
|
||||
|
||||
if (maxIndex <= MAX_8BIT_INTEGER)
|
||||
return Uint8Array;
|
||||
|
||||
if (maxIndex <= MAX_16BIT_INTEGER)
|
||||
return Uint16Array;
|
||||
|
||||
if (maxIndex <= MAX_32BIT_INTEGER)
|
||||
return Uint32Array;
|
||||
|
||||
throw new Error('mnemonist: Pointer Array of size > 4294967295 is not supported.');
|
||||
};
|
||||
|
||||
exports.getSignedPointerArray = function(size) {
|
||||
var maxIndex = size - 1;
|
||||
|
||||
if (maxIndex <= MAX_SIGNED_8BIT_INTEGER)
|
||||
return Int8Array;
|
||||
|
||||
if (maxIndex <= MAX_SIGNED_16BIT_INTEGER)
|
||||
return Int16Array;
|
||||
|
||||
if (maxIndex <= MAX_SIGNED_32BIT_INTEGER)
|
||||
return Int32Array;
|
||||
|
||||
return Float64Array;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function returning the minimal type able to represent the given number.
|
||||
*
|
||||
* @param {number} value - Value to test.
|
||||
* @return {TypedArrayClass}
|
||||
*/
|
||||
exports.getNumberType = function(value) {
|
||||
|
||||
// <= 32 bits itnteger?
|
||||
if (value === (value | 0)) {
|
||||
|
||||
// Negative
|
||||
if (Math.sign(value) === -1) {
|
||||
if (value <= 127 && value >= -128)
|
||||
return Int8Array;
|
||||
|
||||
if (value <= 32767 && value >= -32768)
|
||||
return Int16Array;
|
||||
|
||||
return Int32Array;
|
||||
}
|
||||
else {
|
||||
|
||||
if (value <= 255)
|
||||
return Uint8Array;
|
||||
|
||||
if (value <= 65535)
|
||||
return Uint16Array;
|
||||
|
||||
return Uint32Array;
|
||||
}
|
||||
}
|
||||
|
||||
// 53 bits integer & floats
|
||||
// NOTE: it's kinda hard to tell whether we could use 32bits or not...
|
||||
return Float64Array;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function returning the minimal type able to represent the given array
|
||||
* of JavaScript numbers.
|
||||
*
|
||||
* @param {array} array - Array to represent.
|
||||
* @param {function} getter - Optional getter.
|
||||
* @return {TypedArrayClass}
|
||||
*/
|
||||
var TYPE_PRIORITY = {
|
||||
Uint8Array: 1,
|
||||
Int8Array: 2,
|
||||
Uint16Array: 3,
|
||||
Int16Array: 4,
|
||||
Uint32Array: 5,
|
||||
Int32Array: 6,
|
||||
Float32Array: 7,
|
||||
Float64Array: 8
|
||||
};
|
||||
|
||||
// TODO: make this a one-shot for one value
|
||||
exports.getMinimalRepresentation = function(array, getter) {
|
||||
var maxType = null,
|
||||
maxPriority = 0,
|
||||
p,
|
||||
t,
|
||||
v,
|
||||
i,
|
||||
l;
|
||||
|
||||
for (i = 0, l = array.length; i < l; i++) {
|
||||
v = getter ? getter(array[i]) : array[i];
|
||||
t = exports.getNumberType(v);
|
||||
p = TYPE_PRIORITY[t.name];
|
||||
|
||||
if (p > maxPriority) {
|
||||
maxPriority = p;
|
||||
maxType = t;
|
||||
}
|
||||
}
|
||||
|
||||
return maxType;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function returning whether the given value is a typed array.
|
||||
*
|
||||
* @param {any} value - Value to test.
|
||||
* @return {boolean}
|
||||
*/
|
||||
exports.isTypedArray = function(value) {
|
||||
return typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView(value);
|
||||
};
|
||||
|
||||
/**
|
||||
* Function used to concat byte arrays.
|
||||
*
|
||||
* @param {...ByteArray}
|
||||
* @return {ByteArray}
|
||||
*/
|
||||
exports.concat = function() {
|
||||
var length = 0,
|
||||
i,
|
||||
o,
|
||||
l;
|
||||
|
||||
for (i = 0, l = arguments.length; i < l; i++)
|
||||
length += arguments[i].length;
|
||||
|
||||
var array = new (arguments[0].constructor)(length);
|
||||
|
||||
for (i = 0, o = 0; i < l; i++) {
|
||||
array.set(arguments[i], o);
|
||||
o += arguments[i].length;
|
||||
}
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function used to initialize a byte array of indices.
|
||||
*
|
||||
* @param {number} length - Length of target.
|
||||
* @return {ByteArray}
|
||||
*/
|
||||
exports.indices = function(length) {
|
||||
var PointerArray = exports.getPointerArray(length);
|
||||
|
||||
var array = new PointerArray(length);
|
||||
|
||||
for (var i = 0; i < length; i++)
|
||||
array[i] = i;
|
||||
|
||||
return array;
|
||||
};
|
||||
18
backend/node_modules/mnemonist/utils/types.d.ts
generated
vendored
Normal file
18
backend/node_modules/mnemonist/utils/types.d.ts
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Mnemonist Generic Types
|
||||
* ========================
|
||||
*
|
||||
* Collection of types used throughout the library.
|
||||
*/
|
||||
export interface IArrayLike {
|
||||
length: number;
|
||||
slice(from: number, to?: number): IArrayLike;
|
||||
}
|
||||
|
||||
export type ArrayLike = IArrayLike | ArrayBuffer;
|
||||
|
||||
export interface IArrayLikeConstructor {
|
||||
new(...args: any[]): ArrayLike;
|
||||
}
|
||||
|
||||
export type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array;
|
||||
81
backend/node_modules/mnemonist/vector.d.ts
generated
vendored
Normal file
81
backend/node_modules/mnemonist/vector.d.ts
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Mnemonist Vector Typings
|
||||
* =========================
|
||||
*/
|
||||
import {IArrayLikeConstructor} from './utils/types';
|
||||
|
||||
type VectorOptions = {
|
||||
initialLength?: number;
|
||||
initialCapacity?: number;
|
||||
policy?: (capacity: number) => number;
|
||||
}
|
||||
|
||||
export default class Vector implements Iterable<number> {
|
||||
|
||||
// Members
|
||||
capacity: number;
|
||||
length: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(ArrayClass: IArrayLikeConstructor, initialCapacityOrOptions: number | VectorOptions);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
set(index: number, value: number): this;
|
||||
reallocate(capacity: number): this;
|
||||
grow(capacity?: number): this;
|
||||
resize(length: number): this;
|
||||
push(value: number): number;
|
||||
pop(): number | undefined;
|
||||
get(index: number): number;
|
||||
forEach(callback: (index: number, value: number, set: this) => void, scope?: any): void;
|
||||
values(): IterableIterator<number>;
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
inspect(): any;
|
||||
toJSON(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(iterable: Iterable<I> | {[key: string]: I}, ArrayClass: IArrayLikeConstructor, capacity?: number): Vector;
|
||||
}
|
||||
|
||||
declare class TypedVector implements Iterable<number> {
|
||||
|
||||
// Members
|
||||
capacity: number;
|
||||
length: number;
|
||||
size: number;
|
||||
|
||||
// Constructor
|
||||
constructor(initialCapacityOrOptions: number | VectorOptions);
|
||||
|
||||
// Methods
|
||||
clear(): void;
|
||||
set(index: number, value: number): this;
|
||||
reallocate(capacity: number): this;
|
||||
grow(capacity?: number): this;
|
||||
resize(length: number): this;
|
||||
push(value: number): number;
|
||||
pop(): number | undefined;
|
||||
get(index: number): number;
|
||||
forEach(callback: (index: number, value: number, set: this) => void, scope?: any): void;
|
||||
values(): IterableIterator<number>;
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
inspect(): any;
|
||||
toJSON(): any;
|
||||
|
||||
// Statics
|
||||
static from<I>(iterable: Iterable<I> | {[key: string]: I}, capacity?: number): TypedVector;
|
||||
}
|
||||
|
||||
export class Int8Vector extends TypedVector {}
|
||||
export class Uint8Vector extends TypedVector {}
|
||||
export class Uint8ClampedVector extends TypedVector {}
|
||||
export class Int16Vector extends TypedVector {}
|
||||
export class Uint16Vector extends TypedVector {}
|
||||
export class Int32Vector extends TypedVector {}
|
||||
export class Uint32Vector extends TypedVector {}
|
||||
export class Float32Vector extends TypedVector {}
|
||||
export class Float64Array extends TypedVector {}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user