You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
3.7 KiB

2 years ago
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generate = exports.compile = void 0;
var boolbase_1 = __importDefault(require("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`
* ```
*/
function compile(parsed) {
var a = parsed[0];
// Subtract 1 from `b`, to convert from one- to zero-indexed.
var 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_1.default.falseFunc;
// When `a` is in the range -1..1, it matches any element (so only `b` is checked).
if (a === -1)
return function (index) { return index <= b; };
if (a === 0)
return function (index) { return index === b; };
// When `b <= 0` and `a === 1`, they match any element.
if (a === 1)
return b < 0 ? boolbase_1.default.trueFunc : function (index) { return 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.
*/
var absA = Math.abs(a);
// Get `b mod a`, + a if this is negative.
var bMod = ((b % absA) + absA) % absA;
return a > 1
? function (index) { return index >= b && index % absA === bMod; }
: function (index) { return index <= b && index % absA === bMod; };
}
exports.compile = compile;
/**
* 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
* ```
*/
function generate(parsed) {
var a = parsed[0];
// Subtract 1 from `b`, to convert from one- to zero-indexed.
var b = parsed[1] - 1;
var n = 0;
// Make sure to always return an increasing sequence
if (a < 0) {
var aPos_1 = -a;
// Get `b mod a`
var minValue_1 = ((b % aPos_1) + aPos_1) % aPos_1;
return function () {
var val = minValue_1 + aPos_1 * n++;
return val > b ? null : val;
};
}
if (a === 0)
return b < 0
? // There are no result — always return `null`
function () { return null; }
: // Return `b` exactly once
function () { return (n++ === 0 ? b : null); };
if (b < 0) {
b += a * Math.ceil(-b / a);
}
return function () { return a * n++ + b; };
}
exports.generate = generate;
//# sourceMappingURL=compile.js.map