205 lines
20 KiB
JavaScript
205 lines
20 KiB
JavaScript
/**
|
|
* SIMD Operations for vector computations
|
|
*
|
|
* Uses native SIMD instructions (AVX2/AVX512/SSE4.1/NEON) when available,
|
|
* falls back to JavaScript implementations otherwise.
|
|
*/
|
|
import { getNativeModule } from './native';
|
|
/**
|
|
* SIMD Operations class
|
|
*
|
|
* Provides hardware-accelerated vector operations when native module is available.
|
|
*
|
|
* @example
|
|
* ```typescript
|
|
* import { SimdOps } from '@ruvector/ruvllm';
|
|
*
|
|
* const simd = new SimdOps();
|
|
*
|
|
* // Compute dot product
|
|
* const result = simd.dotProduct([1, 2, 3], [4, 5, 6]);
|
|
* console.log(result); // 32
|
|
*
|
|
* // Check capabilities
|
|
* console.log(simd.capabilities()); // ['AVX2', 'FMA']
|
|
* ```
|
|
*/
|
|
export class SimdOps {
|
|
constructor() {
|
|
this.native = null;
|
|
const mod = getNativeModule();
|
|
if (mod) {
|
|
try {
|
|
this.native = new mod.SimdOperations();
|
|
}
|
|
catch {
|
|
// Fall back to JS implementation
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Compute dot product of two vectors
|
|
*/
|
|
dotProduct(a, b) {
|
|
if (this.native) {
|
|
return this.native.dotProduct(a, b);
|
|
}
|
|
// JavaScript fallback
|
|
let sum = 0;
|
|
const len = Math.min(a.length, b.length);
|
|
for (let i = 0; i < len; i++) {
|
|
sum += a[i] * b[i];
|
|
}
|
|
return sum;
|
|
}
|
|
/**
|
|
* Compute cosine similarity between two vectors
|
|
*/
|
|
cosineSimilarity(a, b) {
|
|
if (this.native) {
|
|
return this.native.cosineSimilarity(a, b);
|
|
}
|
|
// JavaScript fallback
|
|
let dot = 0;
|
|
let normA = 0;
|
|
let normB = 0;
|
|
const len = Math.min(a.length, b.length);
|
|
for (let i = 0; i < len; i++) {
|
|
dot += a[i] * b[i];
|
|
normA += a[i] * a[i];
|
|
normB += b[i] * b[i];
|
|
}
|
|
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
return denom > 0 ? dot / denom : 0;
|
|
}
|
|
/**
|
|
* Compute L2 (Euclidean) distance between two vectors
|
|
*/
|
|
l2Distance(a, b) {
|
|
if (this.native) {
|
|
return this.native.l2Distance(a, b);
|
|
}
|
|
// JavaScript fallback
|
|
let sum = 0;
|
|
const len = Math.min(a.length, b.length);
|
|
for (let i = 0; i < len; i++) {
|
|
const diff = a[i] - b[i];
|
|
sum += diff * diff;
|
|
}
|
|
return Math.sqrt(sum);
|
|
}
|
|
/**
|
|
* Matrix-vector multiplication
|
|
*/
|
|
matvec(matrix, vector) {
|
|
if (this.native) {
|
|
return this.native.matvec(matrix, vector);
|
|
}
|
|
// JavaScript fallback
|
|
return matrix.map(row => this.dotProduct(row, vector));
|
|
}
|
|
/**
|
|
* Softmax activation function
|
|
*/
|
|
softmax(input) {
|
|
if (this.native) {
|
|
return this.native.softmax(input);
|
|
}
|
|
// JavaScript fallback
|
|
const max = Math.max(...input);
|
|
const exps = input.map(x => Math.exp(x - max));
|
|
const sum = exps.reduce((a, b) => a + b, 0);
|
|
return exps.map(x => x / sum);
|
|
}
|
|
/**
|
|
* Element-wise addition
|
|
*/
|
|
add(a, b) {
|
|
const len = Math.min(a.length, b.length);
|
|
const result = new Array(len);
|
|
for (let i = 0; i < len; i++) {
|
|
result[i] = a[i] + b[i];
|
|
}
|
|
return result;
|
|
}
|
|
/**
|
|
* Element-wise multiplication
|
|
*/
|
|
mul(a, b) {
|
|
const len = Math.min(a.length, b.length);
|
|
const result = new Array(len);
|
|
for (let i = 0; i < len; i++) {
|
|
result[i] = a[i] * b[i];
|
|
}
|
|
return result;
|
|
}
|
|
/**
|
|
* Scale vector by scalar
|
|
*/
|
|
scale(a, scalar) {
|
|
return a.map(x => x * scalar);
|
|
}
|
|
/**
|
|
* Normalize vector to unit length
|
|
*/
|
|
normalize(a) {
|
|
const norm = Math.sqrt(a.reduce((sum, x) => sum + x * x, 0));
|
|
return norm > 0 ? a.map(x => x / norm) : a;
|
|
}
|
|
/**
|
|
* ReLU activation
|
|
*/
|
|
relu(input) {
|
|
return input.map(x => Math.max(0, x));
|
|
}
|
|
/**
|
|
* GELU activation (approximate)
|
|
*/
|
|
gelu(input) {
|
|
return input.map(x => {
|
|
return 0.5 * x * (1 + Math.tanh(Math.sqrt(2 / Math.PI) * (x + 0.044715 * x * x * x)));
|
|
});
|
|
}
|
|
/**
|
|
* Sigmoid activation
|
|
*/
|
|
sigmoid(input) {
|
|
return input.map(x => 1 / (1 + Math.exp(-x)));
|
|
}
|
|
/**
|
|
* Layer normalization
|
|
*/
|
|
layerNorm(input, eps = 1e-5) {
|
|
const mean = input.reduce((a, b) => a + b, 0) / input.length;
|
|
const variance = input.reduce((sum, x) => sum + (x - mean) ** 2, 0) / input.length;
|
|
const std = Math.sqrt(variance + eps);
|
|
return input.map(x => (x - mean) / std);
|
|
}
|
|
/**
|
|
* Check if native SIMD is available
|
|
*/
|
|
isNative() {
|
|
return this.native !== null;
|
|
}
|
|
/**
|
|
* Get available SIMD capabilities
|
|
*/
|
|
capabilities() {
|
|
if (!this.native) {
|
|
return ['JavaScript (scalar)'];
|
|
}
|
|
// The native module will report actual capabilities
|
|
const mod = getNativeModule();
|
|
if (mod) {
|
|
try {
|
|
const engine = new mod.RuvLLMEngine();
|
|
return engine.simdCapabilities();
|
|
}
|
|
catch {
|
|
return ['Native (unknown)'];
|
|
}
|
|
}
|
|
return ['JavaScript (scalar)'];
|
|
}
|
|
}
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2ltZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zaW1kLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7OztHQUtHO0FBRUgsT0FBTyxFQUFFLGVBQWUsRUFBaUIsTUFBTSxVQUFVLENBQUM7QUFFMUQ7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtCRztBQUNILE1BQU0sT0FBTyxPQUFPO0lBR2xCO1FBRlEsV0FBTSxHQUF5QixJQUFJLENBQUM7UUFHMUMsTUFBTSxHQUFHLEdBQUcsZUFBZSxFQUFFLENBQUM7UUFDOUIsSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNSLElBQUksQ0FBQztnQkFDSCxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3pDLENBQUM7WUFBQyxNQUFNLENBQUM7Z0JBQ1AsaUNBQWlDO1lBQ25DLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsVUFBVSxDQUFDLENBQVcsRUFBRSxDQUFXO1FBQ2pDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2hCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3RDLENBQUM7UUFFRCxzQkFBc0I7UUFDdEIsSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDO1FBQ1osTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN6QyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDN0IsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckIsQ0FBQztRQUNELE9BQU8sR0FBRyxDQUFDO0lBQ2Is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QUFJLENBQUMsTUFBTSxLQUFLLElBQUksQ0FBQztJQUM5QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxZQUFZO1FBQ1YsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNqQixPQUFPLENBQUMscUJBQXFCLENBQUMsQ0FBQztRQUNqQyxDQUFDO1FBRUQsb0RBQW9EO1FBQ3BELE1BQU0sR0FBRyxHQUFHLGVBQWUsRUFBRSxDQUFDO1FBQzlCLElBQUksR0FBRyxFQUFFLENBQUM7WUFDUixJQUFJLENBQUM7Z0JBQ0gsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ3RDLE9BQU8sTUFBTSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDbkMsQ0FBQztZQUFDLE1BQU0sQ0FBQztnQkFDUCxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUM5QixDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0lBQ2pDLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogU0lNRCBPcGVyYXRpb25zIGZvciB2ZWN0b3IgY29tcHV0YXRpb25zXG4gKlxuICogVXNlcyBuYXRpdmUgU0lNRCBpbnN0cnVjdGlvbnMgKEFWWDIvQVZYNTEyL1NTRTQuMS9ORU9OKSB3aGVuIGF2YWlsYWJsZSxcbiAqIGZhbGxzIGJhY2sgdG8gSmF2YVNjcmlwdCBpbXBsZW1lbnRhdGlvbnMgb3RoZXJ3aXNlLlxuICovXG5cbmltcG9ydCB7IGdldE5hdGl2ZU1vZHVsZSwgTmF0aXZlU2ltZE9wcyB9IGZyb20gJy4vbmF0aXZlJztcblxuLyoqXG4gKiBTSU1EIE9wZXJhdGlvbnMgY2xhc3NcbiAqXG4gKiBQcm92aWRlcyBoYXJkd2FyZS1hY2NlbGVyYXRlZCB2ZWN0b3Igb3BlcmF0aW9ucyB3aGVuIG5hdGl2ZSBtb2R1bGUgaXMgYXZhaWxhYmxlLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBTaW1kT3BzIH0gZnJvbSAnQHJ1dmVjdG9yL3J1dmxsbSc7XG4gKlxuICogY29uc3Qgc2ltZCA9IG5ldyBTaW1kT3BzKCk7XG4gKlxuICogLy8gQ29tcHV0ZSBkb3QgcHJvZHVjdFxuICogY29uc3QgcmVzdWx0ID0gc2ltZC5kb3RQcm9kdWN0KFsxLCAyLCAzXSwgWzQsIDUsIDZdKTtcbiAqIGNvbnNvbGUubG9nKHJlc3VsdCk7IC8vIDMyXG4gKlxuICogLy8gQ2hlY2sgY2FwYWJpbGl0aWVzXG4gKiBjb25zb2xlLmxvZyhzaW1kLmNhcGFiaWxpdGllcygpKTsgLy8gWydBVlgyJywgJ0ZNQSddXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIFNpbWRPcHMge1xuICBwcml2YXRlIG5hdGl2ZTogTmF0aXZlU2ltZE9wcyB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIGNvbnN0IG1vZCA9IGdldE5hdGl2ZU1vZHVsZSgpO1xuICAgIGlmIChtb2QpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMubmF0aXZlID0gbmV3IG1vZC5TaW1kT3BlcmF0aW9ucygpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIEZhbGwgYmFjayB0byBKUyBpbXBsZW1lbnRhdGlvblxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wdXRlIGRvdCBwcm9kdWN0IG9mIHR3byB2ZWN0b3JzXG4gICAqL1xuICBkb3RQcm9kdWN0KGE6IG51bWJlcltdLCBiOiBudW1iZXJbXSk6IG51bWJlciB7XG4gICAgaWYgKHRoaXMubmF0aXZlKSB7XG4gICAgICByZXR1cm4gdGhpcy5uYXRpdmUuZG90UHJvZHVjdChhLCBiKTtcbiAgICB9XG5cbiAgICAvLyBKYXZhU2NyaXB0IGZhbGxiYWNrXG4gICAgbGV0IHN1bSA9IDA7XG4gICAgY29uc3QgbGVuID0gTWF0aC5taW4oYS5sZW5ndGgsIGIubGVuZ3RoKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBzdW0gKz0gYVtpXSAqIGJbaV07XG4gICAgfVxuICAgIHJldHVybiBzdW07XG4gIH1cblxuICAvKipcbiAgICogQ29tcHV0ZSBjb3NpbmUgc2ltaWxhcml0eSBiZXR3ZWVuIHR3byB2ZWN0b3JzXG4gICAqL1xuICBjb3NpbmVTaW1pbGFyaXR5KGE6IG51bWJlcltdLCBiOiBudW1iZXJbXSk6IG51bWJlciB7XG4gICAgaWYgKHRoaXMubmF0aXZlKSB7XG4gICAgICByZXR1cm4gdGhpcy5uYXRpdmUuY29zaW5lU2ltaWxhcml0eShhLCBiKTtcbiAgICB9XG5cbiAgICAvLyBKYXZhU2NyaXB0IGZhbGxiYWNrXG4gICAgbGV0IGRvdCA9IDA7XG4gICAgbGV0IG5vcm1BID0gMDtcbiAgICBsZXQgbm9ybUIgPSAwO1xuXG4gICAgY29uc3QgbGVuID0gTWF0aC5taW4oYS5sZW5ndGgsIGIubGVuZ3RoKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBkb3QgKz0gYVtpXSAqIGJbaV07XG4gICAgICBub3JtQSArPSBhW2ldICogYVtpXTtcbiAgICAgIG5vcm1CICs9IGJbaV0gKiBiW2ldO1xuICAgIH1cblxuICAgIGNvbnN0IGRlbm9tID0gTWF0aC5zcXJ0KG5vcm1BKSAqIE1hdGguc3FydChub3JtQik7XG4gICAgcmV0dXJuIGRlbm9tID4gMCA/IGRvdCAvIGRlbm9tIDogMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wdXRlIEwyIChFdWNsaWRlYW4pIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlY3RvcnNcbiAgICovXG4gIGwyRGlzdGFuY2UoYTogbnVtYmVyW10sIGI6IG51bWJlcltdKTogbnVtYmVyIHtcbiAgICBpZiAodGhpcy5uYXRpdmUpIHtcbiAgICAgIHJldHVybiB0aGlzLm5hdGl2ZS5sMkRpc3RhbmNlKGEsIGIpO1xuICAgIH1cblxuICAgIC8vIEphdmFTY3JpcHQgZmFsbGJhY2tcbiAgICBsZXQgc3VtID0gMDtcbiAgICBjb25zdCBsZW4gPSBNYXRoLm1pbihhLmxlbmd0aCwgYi5sZW5ndGgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGNvbnN0IGRpZmYgPSBhW2ldIC0gYltpXTtcbiAgICAgIHN1bSArPSBkaWZmICogZGlmZjtcbiAgICB9XG4gICAgcmV0dXJuIE1hdGguc3FydChzdW0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1hdHJpeC12ZWN0b3IgbXVsdGlwbGljYXRpb25cbiAgICovXG4gIG1hdHZlYyhtYXRyaXg6IG51bWJlcltdW10sIHZlY3RvcjogbnVtYmVyW10pOiBudW1iZXJbXSB7XG4gICAgaWYgKHRoaXMubmF0aXZlKSB7XG4gICAgICByZXR1cm4gdGhpcy5uYXRpdmUubWF0dmVjKG1hdHJpeCwgdmVjdG9yKTtcbiAgICB9XG5cbiAgICAvLyBKYXZhU2NyaXB0IGZhbGxiYWNrXG4gICAgcmV0dXJuIG1hdHJpeC5tYXAocm93ID0+IHRoaXMuZG90UHJvZHVjdChyb3csIHZlY3RvcikpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNvZnRtYXggYWN0aXZhdGlvbiBmdW5jdGlvblxuICAgKi9cbiAgc29mdG1heChpbnB1dDogbnVtYmVyW10pOiBudW1iZXJbXSB7XG4gICAgaWYgKHRoaXMubmF0aXZlKSB7XG4gICAgICByZXR1cm4gdGhpcy5uYXRpdmUuc29mdG1heChpbnB1dCk7XG4gICAgfVxuXG4gICAgLy8gSmF2YVNjcmlwdCBmYWxsYmFja1xuICAgIGNvbnN0IG1heCA9IE1hdGgubWF4KC4uLmlucHV0KTtcbiAgICBjb25zdCBleHBzID0gaW5wdXQubWFwKHggPT4gTWF0aC5leHAoeCAtIG1heCkpO1xuICAgIGNvbnN0IHN1bSA9IGV4cHMucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCk7XG4gICAgcmV0dXJuIGV4cHMubWFwKHggPT4geCAvIHN1bSk7XG4gIH1cblxuICAvKipcbiAgICogRWxlbWVudC13aXNlIGFkZGl0aW9uXG4gICAqL1xuICBhZGQoYTogbnVtYmVyW10sIGI6IG51bWJlcltdKTogbnVtYmVyW10ge1xuICAgIGNvbnN0IGxlbiA9IE1hdGgubWluKGEubGVuZ3RoLCBiLmxlbmd0aCk7XG4gICAgY29uc3QgcmVzdWx0ID0gbmV3IEFycmF5KGxlbik7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgcmVzdWx0W2ldID0gYVtpXSArIGJbaV07XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogRWxlbWVudC13aXNlIG11bHRpcGxpY2F0aW9uXG4gICAqL1xuICBtdWwoYTogbnVtYmVyW10sIGI6IG51bWJlcltdKTogbnVtYmVyW10ge1xuICAgIGNvbnN0IGxlbiA9IE1hdGgubWluKGEubGVuZ3RoLCBiLmxlbmd0aCk7XG4gICAgY29uc3QgcmVzdWx0ID0gbmV3IEFycmF5KGxlbik7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgcmVzdWx0W2ldID0gYVtpXSAqIGJbaV07XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogU2NhbGUgdmVjdG9yIGJ5IHNjYWxhclxuICAgKi9cbiAgc2NhbGUoYTogbnVtYmVyW10sIHNjYWxhcjogbnVtYmVyKTogbnVtYmVyW10ge1xuICAgIHJldHVybiBhLm1hcCh4ID0+IHggKiBzY2FsYXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIE5vcm1hbGl6ZSB2ZWN0b3IgdG8gdW5pdCBsZW5ndGhcbiAgICovXG4gIG5vcm1hbGl6ZShhOiBudW1iZXJbXSk6IG51bWJlcltdIHtcbiAgICBjb25zdCBub3JtID0gTWF0aC5zcXJ0KGEucmVkdWNlKChzdW0sIHgpID0+IHN1bSArIHggKiB4LCAwKSk7XG4gICAgcmV0dXJuIG5vcm0gPiAwID8gYS5tYXAoeCA9PiB4IC8gbm9ybSkgOiBhO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlTFUgYWN0aXZhdGlvblxuICAgKi9cbiAgcmVsdShpbnB1dDogbnVtYmVyW10pOiBudW1iZXJbXSB7XG4gICAgcmV0dXJuIGlucHV0Lm1hcCh4ID0+IE1hdGgubWF4KDAsIHgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHRUxVIGFjdGl2YXRpb24gKGFwcHJveGltYXRlKVxuICAgKi9cbiAgZ2VsdShpbnB1dDogbnVtYmVyW10pOiBudW1iZXJbXSB7XG4gICAgcmV0dXJuIGlucHV0Lm1hcCh4ID0+IHtcbiAgICAgIHJldHVybiAwLjUgKiB4ICogKDEgKyBNYXRoLnRhbmgoTWF0aC5zcXJ0KDIgLyBNYXRoLlBJKSAqICh4ICsgMC4wNDQ3MTUgKiB4ICogeCAqIHgpKSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU2lnbW9pZCBhY3RpdmF0aW9uXG4gICAqL1xuICBzaWdtb2lkKGlucHV0OiBudW1iZXJbXSk6IG51bWJlcltdIHtcbiAgICByZXR1cm4gaW5wdXQubWFwKHggPT4gMSAvICgxICsgTWF0aC5leHAoLXgpKSk7XG4gIH1cblxuICAvKipcbiAgICogTGF5ZXIgbm9ybWFsaXphdGlvblxuICAgKi9cbiAgbGF5ZXJOb3JtKGlucHV0OiBudW1iZXJbXSwgZXBzID0gMWUtNSk6IG51bWJlcltdIHtcbiAgICBjb25zdCBtZWFuID0gaW5wdXQucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCkgLyBpbnB1dC5sZW5ndGg7XG4gICAgY29uc3QgdmFyaWFuY2UgPSBpbnB1dC5yZWR1Y2UoKHN1bSwgeCkgPT4gc3VtICsgKHggLSBtZWFuKSAqKiAyLCAwKSAvIGlucHV0Lmxlbmd0aDtcbiAgICBjb25zdCBzdGQgPSBNYXRoLnNxcnQodmFyaWFuY2UgKyBlcHMpO1xuICAgIHJldHVybiBpbnB1dC5tYXAoeCA9PiAoeCAtIG1lYW4pIC8gc3RkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBuYXRpdmUgU0lNRCBpcyBhdmFpbGFibGVcbiAgICovXG4gIGlzTmF0aXZlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm5hdGl2ZSAhPT0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYXZhaWxhYmxlIFNJTUQgY2FwYWJpbGl0aWVzXG4gICAqL1xuICBjYXBhYmlsaXRpZXMoKTogc3RyaW5nW10ge1xuICAgIGlmICghdGhpcy5uYXRpdmUpIHtcbiAgICAgIHJldHVybiBbJ0phdmFTY3JpcHQgKHNjYWxhciknXTtcbiAgICB9XG5cbiAgICAvLyBUaGUgbmF0aXZlIG1vZHVsZSB3aWxsIHJlcG9ydCBhY3R1YWwgY2FwYWJpbGl0aWVzXG4gICAgY29uc3QgbW9kID0gZ2V0TmF0aXZlTW9kdWxlKCk7XG4gICAgaWYgKG1vZCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgZW5naW5lID0gbmV3IG1vZC5SdXZMTE1FbmdpbmUoKTtcbiAgICAgICAgcmV0dXJuIGVuZ2luZS5zaW1kQ2FwYWJpbGl0aWVzKCk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIFsnTmF0aXZlICh1bmtub3duKSddO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBbJ0phdmFTY3JpcHQgKHNjYWxhciknXTtcbiAgfVxufVxuIl19
|