import boolbase from "boolbase"; /** * Returns a function that checks if an elements index matches the given rule * highly optimized to return the fastest solution. * * @param parsed A tuple [a, b], as returned by `parse`. * @returns A highly optimized function that returns whether an index matches the nth-check. * @example * * ```js * const check = nthCheck.compile([2, 3]); * * check(0); // `false` * check(1); // `false` * check(2); // `true` * check(3); // `false` * check(4); // `true` * check(5); // `false` * check(6); // `true` * ``` */ export function compile(parsed) { const a = parsed[0]; // Subtract 1 from `b`, to convert from one- to zero-indexed. const b = parsed[1] - 1; /* * When `b <= 0`, `a * n` won't be lead to any matches for `a < 0`. * Besides, the specification states that no elements are * matched when `a` and `b` are 0. * * `b < 0` here as we subtracted 1 from `b` above. */ if (b < 0 && a <= 0) return boolbase.falseFunc; // When `a` is in the range -1..1, it matches any element (so only `b` is checked). if (a === -1) return (index) => index <= b; if (a === 0) return (index) => index === b; // When `b <= 0` and `a === 1`, they match any element. if (a === 1) return b < 0 ? boolbase.trueFunc : (index) => index >= b; /* * Otherwise, modulo can be used to check if there is a match. * * Modulo doesn't care about the sign, so let's use `a`s absolute value. */ const absA = Math.abs(a); // Get `b mod a`, + a if this is negative. const bMod = ((b % absA) + absA) % absA; return a > 1 ? (index) => index >= b && index % absA === bMod : (index) => index <= b && index % absA === bMod; } /** * Returns a function that produces a monotonously increasing sequence of indices. * * If the sequence has an end, the returned function will return `null` after * the last index in the sequence. * * @param parsed A tuple [a, b], as returned by `parse`. * @returns A function that produces a sequence of indices. * @example Always increasing (2n+3) * * ```js * const gen = nthCheck.generate([2, 3]) * * gen() // `1` * gen() // `3` * gen() // `5` * gen() // `8` * gen() // `11` * ``` * * @example With end value (-2n+10) * * ```js * * const gen = nthCheck.generate([-2, 5]); * * gen() // 0 * gen() // 2 * gen() // 4 * gen() // null * ``` */ export function generate(parsed) { const a = parsed[0]; // Subtract 1 from `b`, to convert from one- to zero-indexed. let b = parsed[1] - 1; let n = 0; // Make sure to always return an increasing sequence if (a < 0) { const aPos = -a; // Get `b mod a` const minValue = ((b % aPos) + aPos) % aPos; return () => { const val = minValue + aPos * n++; return val > b ? null : val; }; } if (a === 0) return b < 0 ? // There are no result — always return `null` () => null : // Return `b` exactly once () => (n++ === 0 ? b : null); if (b < 0) { b += a * Math.ceil(-b / a); } return () => a * n++ + b; } //# sourceMappingURL=compile.js.map