@@ -46,11 +46,45 @@ export type IntegerRangeOptions = {
4646 * assertEquals([...integerRange(5, 1, { step: -1 })], [5, 4, 3, 2]);
4747 * ```
4848 */
49- export function * integerRange (
49+ export function integerRange (
5050 start : number ,
5151 end : number ,
5252 options ?: IntegerRangeOptions ,
53+ ) : Generator < number , undefined , undefined > ;
54+
55+ /**
56+ * Creates a generator that yields integers in a range from 0 to `end`.
57+ *
58+ * Using the default options, yielded numbers are in the interval `[0, end)` with step size `1`.
59+ *
60+ * @param end The end of the range (exclusive by default)
61+ * @param options Options for the range
62+ * @returns A generator yielding integers in the specified range
63+ *
64+ * @example Usage
65+ * ```ts
66+ * import { integerRange } from "@std/math/integer-range";
67+ * import { assertEquals } from "@std/assert";
68+ * assertEquals([...integerRange(5)], [0, 1, 2, 3, 4]);
69+ * ```
70+ */
71+ export function integerRange (
72+ end : number ,
73+ options ?: IntegerRangeOptions ,
74+ ) : Generator < number , undefined , undefined > ;
75+ // deno-lint-ignore deno-style-guide/exported-function-args-maximum
76+ export function * integerRange (
77+ startOrEnd : number ,
78+ endOrOptions ?: number | IntegerRangeOptions ,
79+ maybeOptions ?: IntegerRangeOptions ,
5380) : Generator < number , undefined , undefined > {
81+ const hasStart = typeof endOrOptions === "number" ;
82+ const [ start , end , options ] = [
83+ hasStart ? startOrEnd : 0 ,
84+ hasStart ? endOrOptions : startOrEnd ,
85+ hasStart ? maybeOptions : endOrOptions ,
86+ ] ;
87+
5488 const { step = 1 , includeStart = true , includeEnd = false } = options ?? { } ;
5589 if ( step === 0 ) throw new RangeError ( "`step` must not be zero" ) ;
5690 for ( const [ k , v ] of Object . entries ( { start, end, step } ) ) {
@@ -59,12 +93,18 @@ export function* integerRange(
5993 }
6094 }
6195
96+ if ( start === end && ! ( includeStart && includeEnd ) ) return ;
97+
6298 const limitsSign = Math . sign ( end - start ) ;
6399 const stepSign = Math . sign ( step ) ;
64100 if ( limitsSign !== 0 && limitsSign !== stepSign ) return ;
65101
66102 if ( includeStart ) yield start ;
67- if ( start > end ) { for ( let i = start + step ; i > end ; i += step ) yield i ; }
68- else for ( let i = start + step ; i < end ; i += step ) yield i ;
69- if ( includeEnd && ( start !== end || ! includeStart ) ) yield end ;
103+
104+ let i = 0 ;
105+ const delta = Math . abs ( step ) ;
106+ const maxDelta = Math . abs ( end - start ) ;
107+ for ( i += delta ; i < maxDelta ; i += delta ) yield start + ( i * stepSign ) ;
108+
109+ if ( includeEnd && ( i * stepSign ) + start === end ) yield end ;
70110}
0 commit comments