UNPKG

molstar

Version:

A comprehensive macromolecular library.

477 lines 15.1 kB
"use strict"; /** * Copyright (c) 2017-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.indicesOf = exports.deduplicate = exports.subtract = exports.intersect = exports.intersectionSize = exports.union = exports.isSubset = exports.areIntersecting = exports.findRange = exports.findPredecessorIndexInInterval = exports.findPredecessorIndex = exports.areEqual = exports.getAt = exports.has = exports.indexOfInRange = exports.indexOfInInterval = exports.indexOf = exports.toString = exports.hashCode = exports.size = exports.max = exports.min = exports.end = exports.start = exports.isRange = exports.is = exports.ofRange = exports.ofUnsortedArray = exports.ofSortedArray = exports.ofSingleton = exports.Empty = void 0; var util_1 = require("../../util"); var interval_1 = require("../interval"); exports.Empty = []; function ofSingleton(v) { return [v]; } exports.ofSingleton = ofSingleton; function ofSortedArray(xs) { return xs; } exports.ofSortedArray = ofSortedArray; function ofUnsortedArray(xs) { (0, util_1.sortArray)(xs); return xs; } exports.ofUnsortedArray = ofUnsortedArray; function ofRange(min, max) { if (max < min) return []; var ret = new Int32Array(max - min + 1); for (var i = min; i <= max; i++) ret[i - min] = i; return ret; } exports.ofRange = ofRange; function is(xs) { return xs && (Array.isArray(xs) || !!xs.buffer); } exports.is = is; function isRange(xs) { return xs[xs.length - 1] - xs[0] + 1 === xs.length; } exports.isRange = isRange; function start(xs) { return xs[0]; } exports.start = start; function end(xs) { return xs[xs.length - 1] + 1; } exports.end = end; function min(xs) { return xs[0]; } exports.min = min; function max(xs) { return xs[xs.length - 1]; } exports.max = max; function size(xs) { return xs.length; } exports.size = size; function hashCode(xs) { // hash of tuple (size, min, max, mid) var s = xs.length; if (!s) return 0; if (s > 2) return (0, util_1.hash4)(s, xs[0], xs[s - 1], xs[s >> 1]); return (0, util_1.hash3)(s, xs[0], xs[s - 1]); } exports.hashCode = hashCode; function toString(xs) { var s = xs.length; if (s > 5) return "[" + xs[0] + ", " + xs[1] + ", ..., " + xs[s - 1] + "], length " + s; return "[" + xs.join(', ') + "]"; } exports.toString = toString; /** Returns the index of `x` in `set` or -1 if not found. */ function indexOf(xs, v) { var l = xs.length; return l === 0 ? -1 : xs[0] <= v && v <= xs[l - 1] ? binarySearchRange(xs, v, 0, l) : -1; } exports.indexOf = indexOf; function indexOfInInterval(xs, v, bounds) { return indexOfInRange(xs, v, interval_1.Interval.start(bounds), interval_1.Interval.end(bounds)); } exports.indexOfInInterval = indexOfInInterval; function indexOfInRange(xs, v, s, e) { var l = xs.length; return l === 0 || e <= s ? -1 : xs[s] <= v && v <= xs[e - 1] ? binarySearchRange(xs, v, s, e) : -1; } exports.indexOfInRange = indexOfInRange; function has(xs, v) { return indexOf(xs, v) >= 0; } exports.has = has; function getAt(xs, i) { return xs[i]; } exports.getAt = getAt; function areEqual(a, b) { if (a === b) return true; var aSize = a.length; if (aSize !== b.length || a[0] !== b[0] || a[aSize - 1] !== b[aSize - 1]) return false; if (isRange(a)) return true; aSize--; for (var i = 1; i < aSize; i++) { if (a[i] !== b[i]) return false; } return true; } exports.areEqual = areEqual; /** * Returns 0 if `v` is smaller or equal the first element of `xs` * Returns length of `xs` if `v` is bigger than the last element of `xs` * Otherwise returns the first index where the value of `xs` is equal or bigger than `v` */ function findPredecessorIndex(xs, v) { var len = xs.length; if (v <= xs[0]) return 0; if (v > xs[len - 1]) return len; return binarySearchPredIndexRange(xs, v, 0, len); } exports.findPredecessorIndex = findPredecessorIndex; function findPredecessorIndexInInterval(xs, v, bounds) { var s = interval_1.Interval.start(bounds), e = interval_1.Interval.end(bounds); var sv = xs[s]; if (v <= sv) return s; if (e > s && v > xs[e - 1]) return e; // do a linear search if there are only 10 or less items remaining if (v - sv <= 11) return linearSearchPredInRange(xs, v, s + 1, e); return binarySearchPredIndexRange(xs, v, s, e); } exports.findPredecessorIndexInInterval = findPredecessorIndexInInterval; function findRange(xs, min, max) { return interval_1.Interval.ofBounds(findPredecessorIndex(xs, min), findPredecessorIndex(xs, max + 1)); } exports.findRange = findRange; function binarySearchRange(xs, value, start, end) { var min = start, max = end - 1; while (min <= max) { // do a linear search if there are only 10 or less items remaining if (min + 11 > max) { for (var i = min; i <= max; i++) { if (value === xs[i]) return i; } return -1; } var mid = (min + max) >> 1; var v = xs[mid]; if (value < v) max = mid - 1; else if (value > v) min = mid + 1; else return mid; } return -1; } function binarySearchPredIndexRange(xs, value, start, end) { var min = start, max = end - 1; while (min < max) { // do a linear search if there are only 10 or less items remaining if (min + 11 > max) { for (var i = min; i <= max; i++) { if (value <= xs[i]) return i; } return max + 1; } var mid = (min + max) >> 1; var v = xs[mid]; if (value < v) max = mid - 1; else if (value > v) min = mid + 1; else return mid; } if (min > max) return max + 1; return xs[min] >= value ? min : min + 1; } function linearSearchPredInRange(xs, value, start, end) { for (var i = start; i < end; i++) { if (value <= xs[i]) return i; } return end; } function areIntersecting(a, b) { if (a === b) return true; var _a = getSuitableIntersectionRange(a, b), i = _a.startI, j = _a.startJ, endI = _a.endI, endJ = _a.endJ; while (i < endI && j < endJ) { var x = a[i], y = b[j]; if (x < y) i++; else if (x > y) j++; else return true; } return false; } exports.areIntersecting = areIntersecting; function isSubset(a, b) { if (a === b) return true; var lenB = b.length; var _a = getSuitableIntersectionRange(a, b), i = _a.startI, j = _a.startJ, endI = _a.endI, endJ = _a.endJ; // must be able to advance by lenB elements if (endJ - j < lenB || endI - i < lenB) return false; var equal = 0; while (i < endI && j < endJ) { var x = a[i], y = b[j]; if (x < y) { i++; } else if (x > y) { j++; } else { i++; j++; equal++; } } return equal === lenB; } exports.isSubset = isSubset; function union(a, b) { if (a === b) return a; var lenA = a.length, lenB = b.length; if (lenA === 0) return b; if (lenB === 0) return a; if (a[0] > b[0]) return union(b, a); var _a = getSuitableIntersectionRange(a, b), startI = _a.startI, startJ = _a.startJ, endI = _a.endI, endJ = _a.endJ; var commonCount = getCommonCount(a, b, startI, startJ, endI, endJ); // A === B || B is subset of A ==> A if ((commonCount === lenA && commonCount === lenB) || commonCount === lenB) return a; // A is subset of B ===> B if (commonCount === lenA) return b; var indices = new Int32Array(lenA + lenB - commonCount); var i = 0, j = 0, offset = 0; // insert the "prefixes" for (i = 0; i < startI; i++) indices[offset++] = a[i]; while (j < endJ && a[startI] > b[j]) indices[offset++] = b[j++]; // insert the common part while (i < endI && j < endJ) { var x = a[i], y = b[j]; if (x < y) { indices[offset++] = x; i++; } else if (x > y) { indices[offset++] = y; j++; } else { indices[offset++] = x; i++; j++; } } // insert the remaining common part for (; i < endI; i++) indices[offset++] = a[i]; for (; j < endJ; j++) indices[offset++] = b[j]; // insert the "tail" for (; i < lenA; i++) indices[offset++] = a[i]; for (; j < lenB; j++) indices[offset++] = b[j]; return ofSortedArray(indices); } exports.union = union; function intersectionSize(a, b) { if (a === b) return size(a); var _a = getSuitableIntersectionRange(a, b), startI = _a.startI, startJ = _a.startJ, endI = _a.endI, endJ = _a.endJ; return getCommonCount(a, b, startI, startJ, endI, endJ); } exports.intersectionSize = intersectionSize; function getCommonCount(a, b, startI, startJ, endI, endJ) { var i = startI, j = startJ; var commonCount = 0; while (i < endI && j < endJ) { var x = a[i], y = b[j]; if (x < y) { i++; } else if (x > y) { j++; } else { i++; j++; commonCount++; } } return commonCount; } function intersect(a, b) { if (a === b) return a; var _a = getSuitableIntersectionRange(a, b), startI = _a.startI, startJ = _a.startJ, endI = _a.endI, endJ = _a.endJ; var commonCount = getCommonCount(a, b, startI, startJ, endI, endJ); var lenA = a.length, lenB = b.length; // no common elements if (!commonCount) return exports.Empty; // A === B || B is subset of A ==> B if ((commonCount === lenA && commonCount === lenB) || commonCount === lenB) return b; // A is subset of B ==> A if (commonCount === lenA) return a; var indices = new Int32Array(commonCount); var offset = 0; var i = startI; var j = startJ; while (i < endI && j < endJ) { var x = a[i], y = b[j]; if (x < y) { i++; } else if (x > y) { j++; } else { indices[offset++] = x; i++; j++; } } return ofSortedArray(indices); } exports.intersect = intersect; function subtract(a, b) { if (a === b) return exports.Empty; var lenA = a.length; var _a = getSuitableIntersectionRange(a, b), sI = _a.startI, sJ = _a.startJ, endI = _a.endI, endJ = _a.endJ; var i = sI, j = sJ; var commonCount = 0; while (i < endI && j < endJ) { var x = a[i], y = b[j]; if (x < y) { i++; } else if (x > y) { j++; } else { i++; j++; commonCount++; } } // A isnt intersecting B ===> A if (!commonCount) return a; // A === B || A is subset of B ===> Empty if (commonCount >= lenA) return exports.Empty; var indices = new Int32Array(lenA - commonCount); var offset = 0; // insert the "prefix" for (var k = 0; k < sI; k++) indices[offset++] = a[k]; i = sI; j = sJ; while (i < endI && j < endJ) { var x = a[i], y = b[j]; if (x < y) { indices[offset++] = x; i++; } else if (x > y) { j++; } else { i++; j++; } } // insert the "tail" for (; i < lenA; i++) indices[offset++] = a[i]; return ofSortedArray(indices); } exports.subtract = subtract; function deduplicate(xs) { if (xs.length < 2) return xs; var count = 1; for (var i = 0, _i = xs.length - 1; i < _i; i++) { if (xs[i] !== xs[i + 1]) count++; } if (count === xs.length) return xs; var ret = new Int32Array(count); var o = 0; for (var i = 0, _i = xs.length - 1; i < _i; i++) { if (xs[i] !== xs[i + 1]) ret[o++] = xs[i]; } ret[o] = xs[xs.length - 1]; return ret; } exports.deduplicate = deduplicate; function indicesOf(a, b) { if (areEqual(a, b)) return ofSortedArray((0, util_1.createRangeArray)(0, a.length - 1)); var _a = getSuitableIntersectionRange(a, b), sI = _a.startI, sJ = _a.startJ, endI = _a.endI, endJ = _a.endJ; var i = sI, j = sJ; var commonCount = 0; while (i < endI && j < endJ) { var x = a[i], y = b[j]; if (x < y) { i++; } else if (x > y) { j++; } else { i++; j++; commonCount++; } } var lenA = a.length; // no common elements if (!commonCount) return exports.Empty; // A is subset of B ==> A if (commonCount === lenA) return ofSortedArray((0, util_1.createRangeArray)(0, a.length - 1)); var indices = new Int32Array(commonCount); var offset = 0; i = sI; j = sJ; while (i < endI && j < endJ) { var x = a[i], y = b[j]; if (x < y) { i++; } else if (x > y) { j++; } else { indices[offset++] = i; i++; j++; } } return ofSortedArray(indices); } exports.indicesOf = indicesOf; var _maxIntRangeRet = { startI: 0, startJ: 0, endI: 0, endJ: 0 }; // for small sets, just gets the whole range, for large sets does a bunch of binary searches function getSuitableIntersectionRange(a, b) { var la = a.length, lb = b.length; var ratio = la / lb; if (la >= 128 || lb >= 128 || ratio <= 0.34 || ratio >= 2.99) { _maxIntRangeRet.startI = findPredecessorIndex(a, start(b)); _maxIntRangeRet.startJ = findPredecessorIndex(b, start(a)); _maxIntRangeRet.endI = findPredecessorIndex(a, end(b)); _maxIntRangeRet.endJ = findPredecessorIndex(b, end(a)); } else { _maxIntRangeRet.startI = 0; _maxIntRangeRet.startJ = 0; _maxIntRangeRet.endI = la; _maxIntRangeRet.endJ = lb; } return _maxIntRangeRet; } //# sourceMappingURL=sorted-array.js.map