1 | // Copyright (c) Jupyter Development Team.
|
2 | // Distributed under the terms of the Modified BSD License.
|
3 | /*-----------------------------------------------------------------------------
|
4 | | Copyright (c) 2014-2017, PhosphorJS Contributors
|
5 | |
|
6 | | Distributed under the terms of the BSD 3-Clause License.
|
7 | |
|
8 | | The full license is in the file LICENSE, distributed with this software.
|
9 | |----------------------------------------------------------------------------*/
|
10 | import { IIterator } from './iter';
|
11 |
|
12 | /**
|
13 | * Create an iterator of evenly spaced values.
|
14 | *
|
15 | * @param start - The starting value for the range, inclusive.
|
16 | *
|
17 | * @param stop - The stopping value for the range, exclusive.
|
18 | *
|
19 | * @param step - The distance between each value.
|
20 | *
|
21 | * @returns An iterator which produces evenly spaced values.
|
22 | *
|
23 | * #### Notes
|
24 | * In the single argument form of `range(stop)`, `start` defaults to
|
25 | * `0` and `step` defaults to `1`.
|
26 | *
|
27 | * In the two argument form of `range(start, stop)`, `step` defaults
|
28 | * to `1`.
|
29 | */
|
30 | export function range(
|
31 | start: number,
|
32 | stop?: number,
|
33 | step?: number
|
34 | ): IIterator<number> {
|
35 | if (stop === undefined) {
|
36 | return new RangeIterator(0, start, 1);
|
37 | }
|
38 | if (step === undefined) {
|
39 | return new RangeIterator(start, stop, 1);
|
40 | }
|
41 | return new RangeIterator(start, stop, step);
|
42 | }
|
43 |
|
44 | /**
|
45 | * An iterator which produces a range of evenly spaced values.
|
46 | */
|
47 | export class RangeIterator implements IIterator<number> {
|
48 | /**
|
49 | * Construct a new range iterator.
|
50 | *
|
51 | * @param start - The starting value for the range, inclusive.
|
52 | *
|
53 | * @param stop - The stopping value for the range, exclusive.
|
54 | *
|
55 | * @param step - The distance between each value.
|
56 | */
|
57 | constructor(start: number, stop: number, step: number) {
|
58 | this._start = start;
|
59 | this._stop = stop;
|
60 | this._step = step;
|
61 | this._length = Private.rangeLength(start, stop, step);
|
62 | }
|
63 |
|
64 | /**
|
65 | * Get an iterator over the object's values.
|
66 | *
|
67 | * @returns An iterator which yields the object's values.
|
68 | */
|
69 | iter(): IIterator<number> {
|
70 | return this;
|
71 | }
|
72 |
|
73 | /**
|
74 | * Create an independent clone of the iterator.
|
75 | *
|
76 | * @returns A new independent clone of the iterator.
|
77 | */
|
78 | clone(): IIterator<number> {
|
79 | let result = new RangeIterator(this._start, this._stop, this._step);
|
80 | result._index = this._index;
|
81 | return result;
|
82 | }
|
83 |
|
84 | /**
|
85 | * Get the next value from the iterator.
|
86 | *
|
87 | * @returns The next value from the iterator, or `undefined`.
|
88 | */
|
89 | next(): number | undefined {
|
90 | if (this._index >= this._length) {
|
91 | return undefined;
|
92 | }
|
93 | return this._start + this._step * this._index++;
|
94 | }
|
95 |
|
96 | private _index = 0;
|
97 | private _length: number;
|
98 | private _start: number;
|
99 | private _stop: number;
|
100 | private _step: number;
|
101 | }
|
102 |
|
103 | /**
|
104 | * The namespace for the module implementation details.
|
105 | */
|
106 | namespace Private {
|
107 | /**
|
108 | * Compute the effective length of a range.
|
109 | *
|
110 | * @param start - The starting value for the range, inclusive.
|
111 | *
|
112 | * @param stop - The stopping value for the range, exclusive.
|
113 | *
|
114 | * @param step - The distance between each value.
|
115 | *
|
116 | * @returns The number of steps need to traverse the range.
|
117 | */
|
118 | export function rangeLength(
|
119 | start: number,
|
120 | stop: number,
|
121 | step: number
|
122 | ): number {
|
123 | if (step === 0) {
|
124 | return Infinity;
|
125 | }
|
126 | if (start > stop && step > 0) {
|
127 | return 0;
|
128 | }
|
129 | if (start < stop && step < 0) {
|
130 | return 0;
|
131 | }
|
132 | return Math.ceil((stop - start) / step);
|
133 | }
|
134 | }
|