covutils
Version:
Utilities for creating, transforming, and handling Coverage Data objects.
140 lines (119 loc) • 4.73 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
exports.minMaxOfRange = minMaxOfRange;
exports.reduceRange = reduceRange;
exports.iterateRange = iterateRange;
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
/**
* @external {Range} https://github.com/Reading-eScience-Centre/coverage-jsapi/blob/master/Range.md
*/
/**
* Return the minimum/maximum across all range values, ignoring null's.
*
* @param {Range<number>} range The numeric coverage data range.
* @return {[min,max]} The minimum and maximum values of the range,
* or [undefined, undefined] if the range contains only `null` values.
*/
function minMaxOfRange(range) {
var min = Infinity;
var max = -Infinity;
var fn = function fn(val) {
if (val === null) return;
if (val < min) min = val;
if (val > max) max = val;
};
iterateRange(range, fn);
return min === Infinity ? [undefined, undefined] : [min, max];
}
/**
* Apply a reduce function over the range values.
*
* @param {Range} range The coverage data range.
* @param {function} callback Function to execute on each value in the array with arguments `(previousValue, currentValue)`.
* @param start Value to use as the first argument to the first call of the `callback`.
* @return The reduced value.
*/
function reduceRange(range, callback, start) {
var v1 = start;
var iterFn = function iterFn(v2) {
v1 = callback(v1, v2);
};
iterateRange(range, iterFn);
return v1;
}
/**
* Iterate over all range values and run a function for each value.
* No particular iteration order must be assumed.
*/
function iterateRange(range, fn) {
// We use a precompiled function here for efficiency.
// See below for a slower recursive version.
// Benchmarks compared to recursive version:
// Chrome 46: around 1.03x faster
// Firefox 42: around 2x faster (and around 6x faster than Chrome 46!)
// nest loops from smallest to biggest
var shape = [].concat(_toConsumableArray(range.shape));
shape.sort(function (_ref, _ref2) {
var _ref4 = _slicedToArray(_ref, 2);
var size1 = _ref4[1];
var _ref3 = _slicedToArray(_ref2, 2);
var size2 = _ref3[1];
return size1 - size2;
});
var begin = 'var obj = {}';
var end = '';
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = shape[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _step$value = _slicedToArray(_step.value, 2);
var axis = _step$value[0];
var size = _step$value[1];
begin += '\n for (var i' + axis + '=0; i' + axis + ' < ' + size + '; ++i' + axis + ') {\n obj[\'' + axis + '\'] = i' + axis + '\n ';
end += '}';
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
begin += '\n fn(get(obj))\n ';
var iterateLoop = new Function('return function iterRange (get, fn) { ' + begin + ' ' + end + ' }')(); // eslint-disable-line
iterateLoop(range.get, fn);
}
/*
* Recursive version of iterate(). For reference only.
*
export function iterate (range, fn) {
let get = range.get
let shape = [...range.shape]
// iterate from smallest to biggest dimension
shape.sort(([,size1], [,size2]) => size1 - size2)
let dims = shape.length
function iterateRecurse (obj, axisIdx) {
if (dims === axisIdx) {
fn(get(obj))
} else {
let [axis,size] = shape[axisIdx]
for (let i=0; i < size; i++) {
obj[axis] = i
iterateRecurse(obj, axisIdx+1)
}
}
}
iterateRecurse({}, 0)
}
*/