UNPKG

functionalscript

Version:

FunctionalScript is a purely functional subset of JavaScript

93 lines (92 loc) 2.71 kB
/** * 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), });