forked from muglug/psl
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrange.php
91 lines (79 loc) · 2.47 KB
/
range.php
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<?php
declare(strict_types=1);
namespace Psl\Vec;
use Psl;
/**
* Returns a new list containing the range of numbers from `$start` to `$end`
* inclusive, with the step between elements being `$step` if provided, or 1 by
* default.
*
* If `$start > $end`, it returns a descending range instead of
* an empty one.
*
* If you don't need the items to be enumerated, consider Vec\fill.
*
* Examples:
*
* Vec\range(0, 5)
* => Vec(0, 1, 2, 3, 4, 5)
*
* Vec\range(5, 0)
* => Vec(5, 4, 3, 2, 1, 0)
*
* Vec\range(0.0, 3.0, 0.5)
* => Vec(0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0)
*
* Vec\range(3.0, 0.0, -0.5)
* => Vec(3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 0.0)
*
* @template T of int|float
*
* @param T $start
* @param T $end
* @param T|null $step
*
* @throws Psl\Exception\InvariantViolationException If $start < $end, and $step is negative.
*
* @return list<T>
*
* @psalm-suppress InvalidReturnType
* @psalm-suppress InvalidReturnStatement
* @psalm-suppress InvalidOperand
* @psalm-suppress DocblockTypeContradiction
*
* @see https://github.com/vimeo/psalm/issues/2152#issuecomment-533363310
*/
function range($start, $end, $step = null): array
{
if ((float) $start === (float) $end) {
return [$start];
}
if ($start < $end) {
if (null === $step) {
/** @var T $step */
$step = 1;
}
Psl\invariant($step > 0, 'If $start < $end, then $step must be positive or null.');
$result = [];
Psl\invariant(is_int($step) || is_float($step), '$step must be either an integer or a float.');
for ($i = $start; $i <= $end; $i += $step) {
Psl\invariant(is_int($i) || is_float($i), '$i must be either an integer or a float.');
Psl\invariant(is_int($step) || is_float($step), '$step must be either an integer or a float.');
$result[] = $i;
}
return $result;
}
if (null === $step) {
/** @var T $step */
$step = -1;
}
Psl\invariant($step < 0, 'If $start > $end, then $step must be negative or null.');
$result = [];
Psl\invariant(is_int($step) || is_float($step), '$step must be either an integer or a float.');
for ($i = $start; $i >= $end; $i += $step) {
Psl\invariant(is_int($i) || is_float($i), '$i must be either an integer or a float.');
Psl\invariant(is_int($step) || is_float($step), '$step must be either an integer or a float.');
$result[] = $i;
}
return $result;
}