Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | 1x 36x 35x 35x 4x 1x 21x 21x 21x 20x 20x 20x 20x 20x 8x 8x 8x 8x 8x 8x 8x 8x 32x 31x 7x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 49x 48x 1x 1x | import { Interval, IInterval, NumericValue } from './interval';
/**
* Returns an iterable generator for numbers or bigints in the interval, stepping by `step`.
* Uses integer math for decimals, and native bigint math for bigints.
*/
function getDecimalPlaces(x: number): number {
if (typeof x !== 'number' || !isFinite(x)) return 0;
const s = x.toString();
if (!s.includes('.')) return 0;
return s.split('.')[1].length;
}
export function range(interval: IInterval | string, step: NumericValue = 1): Iterable<NumericValue> {
return (function* () {
try {
const intvl = new Interval(interval);
const start = intvl.a.number;
const end = intvl.b.number;
const startClosed = intvl.a.isClosed;
const endClosed = intvl.b.isClosed;
// If any value is bigint, use bigint math
if (typeof start === 'bigint' || typeof end === 'bigint' || typeof step === 'bigint') {
const startBig = BigInt(start);
const endBig = end !== Infinity ? BigInt(end) : end;
const absStepBig = BigInt(step) < 0n ? -BigInt(step) : BigInt(step);
const ascending = endBig > startBig;
const actualStep = ascending ? absStepBig : -absStepBig;
let current = startBig;
if (!startClosed) current += actualStep;
while (
(ascending && ((current < endBig) || (endClosed && current === endBig))) ||
(!ascending && ((current > endBig) || (endClosed && current === endBig)))
) {
yield current;
current += actualStep;
}
return;
}
// Otherwise, use number math with integer scaling for decimals
const decimals = Math.max(
getDecimalPlaces(Number(start)),
getDecimalPlaces(Number(end)),
getDecimalPlaces(Number(step))
);
const factor = Math.pow(10, decimals);
let current = Math.round(Number(start) * factor);
const endInt = Math.round(Number(end) * factor);
const absStep = Math.abs(Number(step));
const stepInt = Math.round(absStep * factor);
const ascending = end > start;
const actualStep = ascending ? stepInt : -stepInt;
if (!startClosed) current += actualStep;
while (
(ascending && ((current < endInt) || (endClosed && current === endInt))) ||
(!ascending && ((current > endInt) || (endClosed && current === endInt)))
) {
yield current / factor;
current += actualStep;
}
} catch (error: Error | unknown) {
if (error instanceof Error) {
throw new Error(`Invalid interval: ${error.message}`);
}
}
})();
} |