| 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 <caption>Always increasing (2n+3)</caption> |
| * |
| * ```js |
| * const gen = nthCheck.generate([2, 3]) |
| * |
| * gen() // `1` |
| * gen() // `3` |
| * gen() // `5` |
| * gen() // `8` |
| * gen() // `11` |
| * ``` |
| * |
| * @example <caption>With end value (-2n+10)</caption> |
| * |
| * ```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 |