UNPKG

molstar

Version:

A comprehensive macromolecular library.

423 lines 16.7 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.indexedIntersect = exports.forEachSegment = exports.forEach = exports.subtract = exports.intersect = exports.union = exports.intersectionSize = exports.findRange = exports.findPredecessorIndexInInterval = exports.findPredecessorIndex = exports.isSubset = exports.areIntersecting = exports.areEqual = exports.toString = exports.hashCode = exports.end = exports.start = exports.max = exports.min = exports.getAt = exports.indexOf = exports.has = exports.size = exports.ofSortedArray = exports.ofBounds = exports.ofRange = exports.ofSingleton = exports.Empty = void 0; var sorted_array_1 = require("../sorted-array"); var interval_1 = require("../interval"); exports.Empty = interval_1.Interval.Empty; exports.ofSingleton = interval_1.Interval.ofSingleton; exports.ofRange = interval_1.Interval.ofRange; exports.ofBounds = interval_1.Interval.ofBounds; function ofSortedArray(xs) { if (!xs.length) return exports.Empty; // check if the array is just a range if (sorted_array_1.SortedArray.isRange(xs)) return interval_1.Interval.ofRange(xs[0], xs[xs.length - 1]); return xs; } exports.ofSortedArray = ofSortedArray; function size(set) { return interval_1.Interval.is(set) ? interval_1.Interval.size(set) : sorted_array_1.SortedArray.size(set); } exports.size = size; function has(set, x) { return interval_1.Interval.is(set) ? interval_1.Interval.has(set, x) : sorted_array_1.SortedArray.has(set, x); } exports.has = has; /** Returns the index of `x` in `set` or -1 if not found. */ function indexOf(set, x) { return interval_1.Interval.is(set) ? interval_1.Interval.indexOf(set, x) : sorted_array_1.SortedArray.indexOf(set, x); } exports.indexOf = indexOf; function getAt(set, i) { return interval_1.Interval.is(set) ? interval_1.Interval.getAt(set, i) : set[i]; } exports.getAt = getAt; function min(set) { return interval_1.Interval.is(set) ? interval_1.Interval.min(set) : sorted_array_1.SortedArray.min(set); } exports.min = min; function max(set) { return interval_1.Interval.is(set) ? interval_1.Interval.max(set) : sorted_array_1.SortedArray.max(set); } exports.max = max; function start(set) { return interval_1.Interval.is(set) ? interval_1.Interval.start(set) : sorted_array_1.SortedArray.start(set); } exports.start = start; function end(set) { return interval_1.Interval.is(set) ? interval_1.Interval.end(set) : sorted_array_1.SortedArray.end(set); } exports.end = end; function hashCode(set) { return interval_1.Interval.is(set) ? interval_1.Interval.hashCode(set) : sorted_array_1.SortedArray.hashCode(set); } exports.hashCode = hashCode; // TODO: possibly add more hash functions to allow for multilevel hashing. function toString(set) { return interval_1.Interval.is(set) ? interval_1.Interval.toString(set) : sorted_array_1.SortedArray.toString(set); } exports.toString = toString; function areEqual(a, b) { if (interval_1.Interval.is(a)) { if (interval_1.Interval.is(b)) return interval_1.Interval.areEqual(a, b); return areEqualIS(a, b); } else if (interval_1.Interval.is(b)) return areEqualIS(b, a); return sorted_array_1.SortedArray.areEqual(a, b); } exports.areEqual = areEqual; function areIntersecting(a, b) { if (interval_1.Interval.is(a)) { if (interval_1.Interval.is(b)) return interval_1.Interval.areIntersecting(a, b); return areIntersectingSI(b, a); } else if (interval_1.Interval.is(b)) return areIntersectingSI(a, b); return sorted_array_1.SortedArray.areIntersecting(a, b); } exports.areIntersecting = areIntersecting; /** Check if the 2nd argument is a subset of the 1st */ function isSubset(a, b) { if (interval_1.Interval.is(a)) { if (interval_1.Interval.is(b)) return interval_1.Interval.isSubInterval(a, b); return isSubsetIS(a, b); } else if (interval_1.Interval.is(b)) return isSubsetSI(a, b); return sorted_array_1.SortedArray.isSubset(a, b); } exports.isSubset = isSubset; function findPredecessorIndex(set, x) { return interval_1.Interval.is(set) ? interval_1.Interval.findPredecessorIndex(set, x) : sorted_array_1.SortedArray.findPredecessorIndex(set, x); } exports.findPredecessorIndex = findPredecessorIndex; function findPredecessorIndexInInterval(set, x, bounds) { return interval_1.Interval.is(set) ? interval_1.Interval.findPredecessorIndexInInterval(set, x, bounds) : sorted_array_1.SortedArray.findPredecessorIndexInInterval(set, x, bounds); } exports.findPredecessorIndexInInterval = findPredecessorIndexInInterval; function findRange(set, min, max) { return interval_1.Interval.is(set) ? interval_1.Interval.findRange(set, min, max) : sorted_array_1.SortedArray.findRange(set, min, max); } exports.findRange = findRange; function intersectionSize(a, b) { if (interval_1.Interval.is(a)) { if (interval_1.Interval.is(b)) return interval_1.Interval.intersectionSize(a, b); return intersectionSizeSI(b, a); } else if (interval_1.Interval.is(b)) return intersectionSizeSI(a, b); return sorted_array_1.SortedArray.intersectionSize(a, b); } exports.intersectionSize = intersectionSize; function union(a, b) { if (interval_1.Interval.is(a)) { if (interval_1.Interval.is(b)) return unionII(a, b); return unionSI(b, a); } else if (interval_1.Interval.is(b)) return unionSI(a, b); return ofSortedArray(sorted_array_1.SortedArray.union(a, b)); } exports.union = union; function intersect(a, b) { if (interval_1.Interval.is(a)) { if (interval_1.Interval.is(b)) return interval_1.Interval.intersect(a, b); return intersectSI(b, a); } else if (interval_1.Interval.is(b)) return intersectSI(a, b); return ofSortedArray(sorted_array_1.SortedArray.intersect(a, b)); } exports.intersect = intersect; function subtract(a, b) { if (interval_1.Interval.is(a)) { if (interval_1.Interval.is(b)) return subtractII(a, b); return subtractIS(a, b); } else if (interval_1.Interval.is(b)) return subtractSI(a, b); return ofSortedArray(sorted_array_1.SortedArray.subtract(a, b)); } exports.subtract = subtract; function areEqualIS(a, b) { return interval_1.Interval.size(a) === sorted_array_1.SortedArray.size(b) && interval_1.Interval.start(a) === sorted_array_1.SortedArray.start(b) && interval_1.Interval.end(a) === sorted_array_1.SortedArray.end(b); } function areIntersectingSI(a, b) { return a.length !== 0 && interval_1.Interval.size(sorted_array_1.SortedArray.findRange(a, interval_1.Interval.min(b), interval_1.Interval.max(b))) !== 0; } function isSubsetSI(a, b) { var minB = interval_1.Interval.min(b), maxB = interval_1.Interval.max(b); if (maxB - minB + 1 === 0) return true; var minA = sorted_array_1.SortedArray.min(a), maxA = sorted_array_1.SortedArray.max(a); if (minB < minA || maxB > maxA) return false; var r = sorted_array_1.SortedArray.findRange(a, minB, maxB); return interval_1.Interval.size(r) === interval_1.Interval.size(b); } function isSubsetIS(a, b) { var minA = interval_1.Interval.min(a), maxA = interval_1.Interval.max(a); if (maxA - minA + 1 === 0) return false; var minB = sorted_array_1.SortedArray.min(b), maxB = sorted_array_1.SortedArray.max(b); return minB >= minA && maxB <= maxA; } function areRangesIntersecting(a, b) { var sa = size(a), sb = size(b); if (sa === 0 && sb === 0) return true; return sa > 0 && sb > 0 && max(a) >= min(b) && min(a) <= max(b); } function isRangeSubset(a, b) { if (!size(a)) return size(b) === 0; if (!size(b)) return true; return min(a) <= min(b) && max(a) >= max(b); } function unionII(a, b) { if (interval_1.Interval.areEqual(a, b)) return a; var sizeA = interval_1.Interval.size(a), sizeB = interval_1.Interval.size(b); if (!sizeB) return a; if (!sizeA) return b; var minA = interval_1.Interval.min(a), minB = interval_1.Interval.min(b); if (areRangesIntersecting(a, b)) return interval_1.Interval.ofRange(Math.min(minA, minB), Math.max(interval_1.Interval.max(a), interval_1.Interval.max(b))); var lSize, lMin, rSize, rMin; if (minA < minB) { lSize = sizeA; lMin = minA; rSize = sizeB; rMin = minB; } else { lSize = sizeB; lMin = minB; rSize = sizeA; rMin = minA; } var arr = new Int32Array(sizeA + sizeB); for (var i = 0; i < lSize; i++) arr[i] = i + lMin; for (var i = 0; i < rSize; i++) arr[i + lSize] = i + rMin; return ofSortedArray(arr); } function unionSI(a, b) { var bSize = interval_1.Interval.size(b); if (!bSize) return a; // is the array fully contained in the range? if (isRangeSubset(b, a)) return b; var min = interval_1.Interval.min(b), max = interval_1.Interval.max(b); var r = sorted_array_1.SortedArray.findRange(a, min, max); var start = interval_1.Interval.start(r), end = interval_1.Interval.end(r); var indices = new Int32Array(start + (a.length - end) + bSize); var offset = 0; for (var i = 0; i < start; i++) indices[offset++] = a[i]; for (var i = min; i <= max; i++) indices[offset++] = i; for (var i = end, _i = a.length; i < _i; i++) indices[offset++] = a[i]; return ofSortedArray(indices); } function intersectionSizeSI(a, b) { if (!interval_1.Interval.size(b)) return 0; var r = sorted_array_1.SortedArray.findRange(a, interval_1.Interval.min(b), interval_1.Interval.max(b)); return interval_1.Interval.end(r) - interval_1.Interval.start(r); } function intersectSI(a, b) { if (!interval_1.Interval.size(b)) return exports.Empty; var r = sorted_array_1.SortedArray.findRange(a, interval_1.Interval.min(b), interval_1.Interval.max(b)); var start = interval_1.Interval.start(r), end = interval_1.Interval.end(r); var resultSize = end - start; if (!resultSize) return exports.Empty; if (resultSize === a.length) return a; var indices = new Int32Array(resultSize); var offset = 0; for (var i = start; i < end; i++) { indices[offset++] = a[i]; } return ofSortedArray(indices); } function subtractII(a, b) { if (interval_1.Interval.areEqual(a, b)) return exports.Empty; if (!interval_1.Interval.areIntersecting(a, b)) return a; var minA = interval_1.Interval.min(a), maxA = interval_1.Interval.max(a); var minB = interval_1.Interval.min(b), maxB = interval_1.Interval.max(b); if (maxA < minA || maxB < minB) return a; // is A subset of B? ==> Empty if (interval_1.Interval.isSubInterval(b, a)) return exports.Empty; if (interval_1.Interval.isSubInterval(a, b)) { // this splits the interval into two, gotta represent it as a set. var l = minB - minA, r = maxA - maxB; if (l <= 0) return interval_1.Interval.ofRange(maxB + 1, maxB + r); if (r <= 0) return interval_1.Interval.ofRange(minA, minA + l - 1); var ret = new Int32Array(l + r); var offset = 0; for (var i = 0; i < l; i++) ret[offset++] = minA + i; for (var i = 1; i <= r; i++) ret[offset++] = maxB + i; return ofSortedArray(ret); } if (minA < minB) return interval_1.Interval.ofRange(minA, minB - 1); return interval_1.Interval.ofRange(maxB + 1, maxA); } function subtractSI(a, b) { var min = interval_1.Interval.min(b), max = interval_1.Interval.max(b); // is empty? if (max < min) return a; var r = sorted_array_1.SortedArray.findRange(a, min, max); var start = interval_1.Interval.start(r), end = interval_1.Interval.end(r); var resultSize = a.length - (end - start); // A is subset of B if (resultSize <= 0) return exports.Empty; // No common elements if (resultSize === a.length) return a; var ret = new Int32Array(resultSize); var offset = 0; for (var i = 0; i < start; i++) ret[offset++] = a[i]; for (var i = end, _i = a.length; i < _i; i++) ret[offset++] = a[i]; return ofSortedArray(ret); } function subtractIS(a, b) { var min = interval_1.Interval.min(a), max = interval_1.Interval.max(a); // is empty? if (max < min) return a; var rSize = max - min + 1; var interval = sorted_array_1.SortedArray.findRange(b, min, max); var start = interval_1.Interval.start(interval), end = interval_1.Interval.end(interval); var commonCount = end - start; // No common elements. if (commonCount === 0) return a; var resultSize = rSize - commonCount; // A is subset of B if (resultSize <= 0) return exports.Empty; var ret = new Int32Array(resultSize); var li = b.length - 1; var fst = b[Math.min(start, li)], last = b[Math.min(end, li)]; var offset = 0; for (var i = min; i < fst; i++) ret[offset++] = i; for (var i = fst; i <= last; i++) { if (sorted_array_1.SortedArray.indexOfInInterval(b, i, interval) < 0) ret[offset++] = i; } for (var i = last + 1; i <= max; i++) ret[offset++] = i; return ofSortedArray(ret); } function forEach(set, f, ctx) { if (interval_1.Interval.is(set)) { var start_1 = interval_1.Interval.min(set); for (var i = start_1, _i = interval_1.Interval.max(set); i <= _i; i++) { f(i, i - start_1, ctx); } } else { for (var i = 0, _i = set.length; i < _i; i++) { f(set[i], i, ctx); } } return ctx; } exports.forEach = forEach; function forEachSegment(set, segment, f, ctx) { if (interval_1.Interval.is(set)) { var sI = 0; for (var i = interval_1.Interval.min(set), _i = interval_1.Interval.max(set); i <= _i; i++) { var s = segment(i); var endI = i + 1; while (endI < _i && segment(endI) === s) endI++; i = endI - 1; f(s, sI, ctx); sI++; } } else { var sI = 0; for (var i = 0, _i = set.length; i < _i; i++) { var s = segment(set[i]); var endI = i + 1; while (endI < _i && segment(set[endI]) === s) endI++; i = endI - 1; f(s, sI, ctx); sI++; } } return ctx; } exports.forEachSegment = forEachSegment; function indexedIntersect(idxA, a, b) { if (a === b) return idxA; var lenI = size(idxA), lenA = a.length, lenB = b.length; if (lenI === 0 || lenA === 0 || lenB === 0) return exports.Empty; var startJ = sorted_array_1.SortedArray.findPredecessorIndex(b, a[min(idxA)]); var endJ = sorted_array_1.SortedArray.findPredecessorIndex(b, a[max(idxA)] + 1); var commonCount = 0; var offset = 0; var O = 0; var j = startJ; while (O < lenI && j < endJ) { var x = a[getAt(idxA, O)], y = b[j]; if (x < y) { O++; } else if (x > y) { j++; } else { commonCount++; O++; j++; } } // no common elements if (commonCount === 0) return exports.Empty; // A === B if (commonCount === lenA && commonCount === lenB) return idxA; var indices = new Int32Array(commonCount); offset = 0; O = 0; j = startJ; while (O < lenI && j < endJ) { var x = a[getAt(idxA, O)], y = b[j]; if (x < y) { O++; } else if (x > y) { j++; } else { indices[offset++] = j; O++; j++; } } return ofSortedArray(indices); } exports.indexedIntersect = indexedIntersect; //# sourceMappingURL=ordered-set.js.map