functionalscript
Version:
FunctionalScript is a purely functional subset of JavaScript
93 lines (92 loc) • 2.71 kB
JavaScript
/**
* Utility functions and types for managing and merging range maps.
*
* @module
*
* @example
*
* ```js
* const rmOps = rangeMap({
* union: a => b => a | b,
* equal: a => b => a === b,
* def: 0,
* })
*
* // Create range maps
* const range1 = rmOps.fromRange([0, 10])(2)
* const range2 = rmOps.fromRange([5, 15])(5)
*
* // Merge range maps
* const merged = toArray(rmOps.merge(range1)(range2))
*
* // Retrieve values from the merged range map
* //
* if (rmOps.get(-1)(merged) !== 0) { throw 'error' }
* //
* if (rmOps.get(0)(merged) !== 2) { throw 'error' }
* if (rmOps.get(2)(merged) !== 2) { throw 'error' }
* // overlapped: 2 | 5 = 7
* if (rmOps.get(7)(merged) !== 7) { throw 'error' }
* //
* if (rmOps.get(12)(merged) !== 5) { throw 'error' }
* if (rmOps.get(15)(merged) !== 5) { throw 'error' }
* //
* if (rmOps.get(16)(merged) !== 0) { throw 'error' }
* ```
*/
import { genericMerge } from "../sorted_list/module.f.js";
import { next } from "../list/module.f.js";
import { cmp } from "../number/module.f.js";
const reduceOp = ({ union, equal }) => state => ([aItem, aMax]) => ([bItem, bMax]) => {
const sign = cmp(aMax)(bMax);
const min = sign === 1 ? bMax : aMax;
const u = union(aItem)(bItem);
const newState = state !== null && equal(state[0])(u) ? null : state;
return [newState, sign, [u, min]];
};
const tailReduce = equal => state => tail => {
if (state === null) {
return tail;
}
const tailResult = next(tail);
if (tailResult === null) {
return [state];
}
if (equal(state[0])(tailResult.first[0])) {
return tailResult;
}
return { first: state, tail: tailResult };
};
export const merge = op => genericMerge({ reduceOp: reduceOp(op), tailReduce: tailReduce(op.equal) })(null);
export const get = def => value => rm => {
const len = rm.length;
let b = 0;
let e = len - 1;
while (true) {
if (b >= len) {
return def;
}
if (e - b < 0) {
return rm[b][0];
}
const mid = b + (e - b >> 1);
if (value <= rm[mid][1]) {
e = mid - 1;
}
else {
b = mid + 1;
}
}
};
export const fromRange = def => ([a, b]) => v => [[def, a - 1], [v, b]];
/**
* Creates a set of operations for managing range maps using the specified properties.
*
* @param op - The properties defining union and equality operations and the default value.
* @returns An object containing operations for merging, retrieving, and constructing range maps.
*/
export const rangeMap = (op) => ({
merge: merge(op),
get: get(op.def),
fromRange: fromRange(op.def),
});