molstar
Version:
A comprehensive macromolecular library.
423 lines • 16.7 kB
JavaScript
"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