• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37527

pending completion
#37527

push

local

web-flow
make `IRShow.method_name` inferrable (#49607)

18 of 18 new or added lines in 3 files covered. (100.0%)

68710 of 81829 relevant lines covered (83.97%)

33068903.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.18
/base/range.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
(:)(a::Real, b::Real) = (:)(promote(a, b)...)
5,391,519✔
4

5
(:)(start::T, stop::T) where {T<:Real} = UnitRange{T}(start, stop)
2,412,346,916✔
6

7
(:)(start::T, stop::T) where {T} = (:)(start, oftype(stop >= start ? stop - start : start - stop, 1), stop)
67✔
8

9
# promote start and stop, leaving step alone
10
(:)(start::A, step, stop::C) where {A<:Real, C<:Real} =
54✔
11
    (:)(convert(promote_type(A, C), start), step, convert(promote_type(A, C), stop))
12

13
# AbstractFloat specializations
14
(:)(a::T, b::T) where {T<:AbstractFloat} = (:)(a, T(1), b)
1,895✔
15

16
(:)(a::T, b::AbstractFloat, c::T) where {T<:Real} = (:)(promote(a, b, c)...)
169✔
17
(:)(a::T, b::AbstractFloat, c::T) where {T<:AbstractFloat} = (:)(promote(a, b, c)...)
1✔
18
(:)(a::T, b::Real, c::T) where {T<:AbstractFloat} = (:)(promote(a, b, c)...)
439✔
19

20
(:)(start::T, step::T, stop::T) where {T<:AbstractFloat} =
260✔
21
    _colon(OrderStyle(T), ArithmeticStyle(T), start, step, stop)
22
(:)(start::T, step::T, stop::T) where {T<:Real} =
130,228,267✔
23
    _colon(OrderStyle(T), ArithmeticStyle(T), start, step, stop)
24
_colon(::Ordered, ::Any, start::T, step, stop::T) where {T} = StepRange(start, step, stop)
130,228,288✔
25
# for T<:Union{Float16,Float32,Float64} see twiceprecision.jl
26
_colon(::Ordered, ::ArithmeticRounds, start::T, step, stop::T) where {T} =
260✔
27
    StepRangeLen(start, step, convert(Integer, fld(stop - start, step)) + 1)
28
_colon(::Any, ::Any, start::T, step, stop::T) where {T} =
×
29
    StepRangeLen(start, step, convert(Integer, fld(stop - start, step)) + 1)
30

31
"""
32
    (:)(start, [step], stop)
33

34
Range operator. `a:b` constructs a range from `a` to `b` with a step size
35
equal to 1, which produces:
36

37
* a [`UnitRange`](@ref) when `a` and `b` are integers, or
38
* a [`StepRange`](@ref) when `a` and `b` are characters, or
39
* a [`StepRangeLen`](@ref) when `a` and/or `b` are floating-point.
40

41
`a:s:b` is similar but uses a step size of `s` (a [`StepRange`](@ref) or
42
[`StepRangeLen`](@ref)). See also [`range`](@ref) for more control.
43

44
The operator `:` is also used in indexing to select whole dimensions, e.g. in `A[:, 1]`.
45

46
`:` is also used to [`quote`](@ref) code, e.g. `:(x + y) isa Expr` and `:x isa Symbol`.
47
Since `:2 isa Int`, it does *not* create a range in indexing: `v[:2] == v[2] != v[begin:2]`.
48
"""
49
(:)(start::T, step, stop::T) where {T} = _colon(start, step, stop)
166✔
50
(:)(start::T, step, stop::T) where {T<:Real} = _colon(start, step, stop)
1,492✔
51
# without the second method above, the first method above is ambiguous with
52
# (:)(start::A, step, stop::C) where {A<:Real,C<:Real}
53
function _colon(start::T, step, stop::T) where T
1,528✔
54
    T′ = typeof(start+zero(step))
1,529✔
55
    StepRange(convert(T′,start), step, convert(T′,stop))
1,719✔
56
end
57

58
"""
59
    range(start, stop, length)
60
    range(start, stop; length, step)
61
    range(start; length, stop, step)
62
    range(;start, length, stop, step)
63

64
Construct a specialized array with evenly spaced elements and optimized storage (an [`AbstractRange`](@ref)) from the arguments.
65
Mathematically a range is uniquely determined by any three of `start`, `step`, `stop` and `length`.
66
Valid invocations of range are:
67
* Call `range` with any three of `start`, `step`, `stop`, `length`.
68
* Call `range` with two of `start`, `stop`, `length`. In this case `step` will be assumed
69
  to be one. If both arguments are Integers, a [`UnitRange`](@ref) will be returned.
70
* Call `range` with one of `stop` or `length`. `start` and `step` will be assumed to be one.
71

72
See Extended Help for additional details on the returned type.
73

74
# Examples
75
```jldoctest
76
julia> range(1, length=100)
77
1:100
78

79
julia> range(1, stop=100)
80
1:100
81

82
julia> range(1, step=5, length=100)
83
1:5:496
84

85
julia> range(1, step=5, stop=100)
86
1:5:96
87

88
julia> range(1, 10, length=101)
89
1.0:0.09:10.0
90

91
julia> range(1, 100, step=5)
92
1:5:96
93

94
julia> range(stop=10, length=5)
95
6:10
96

97
julia> range(stop=10, step=1, length=5)
98
6:1:10
99

100
julia> range(start=1, step=1, stop=10)
101
1:1:10
102

103
julia> range(; length = 10)
104
Base.OneTo(10)
105

106
julia> range(; stop = 6)
107
Base.OneTo(6)
108

109
julia> range(; stop = 6.5)
110
1.0:1.0:6.0
111
```
112
If `length` is not specified and `stop - start` is not an integer multiple of `step`, a range that ends before `stop` will be produced.
113
```jldoctest
114
julia> range(1, 3.5, step=2)
115
1.0:2.0:3.0
116
```
117

118
Special care is taken to ensure intermediate values are computed rationally.
119
To avoid this induced overhead, see the [`LinRange`](@ref) constructor.
120

121
!!! compat "Julia 1.1"
122
    `stop` as a positional argument requires at least Julia 1.1.
123

124
!!! compat "Julia 1.7"
125
    The versions without keyword arguments and `start` as a keyword argument
126
    require at least Julia 1.7.
127

128
!!! compat "Julia 1.8"
129
    The versions with `stop` as a sole keyword argument,
130
    or `length` as a sole keyword argument require at least Julia 1.8.
131

132

133
# Extended Help
134

135
`range` will produce a `Base.OneTo` when the arguments are Integers and
136
* Only `length` is provided
137
* Only `stop` is provided
138

139
`range` will produce a `UnitRange` when the arguments are Integers and
140
* Only `start`  and `stop` are provided
141
* Only `length` and `stop` are provided
142

143
A `UnitRange` is not produced if `step` is provided even if specified as one.
144
"""
145
function range end
146

147
range(start; stop=nothing, length::Union{Integer,Nothing}=nothing, step=nothing) =
2,292,006✔
148
    _range(start, step, stop, length)
149
range(start, stop; length::Union{Integer,Nothing}=nothing, step=nothing) = _range(start, step, stop, length)
6,394,401✔
150
range(start, stop, length::Integer) = _range(start, nothing, stop, length)
28✔
151

152
range(;start=nothing, stop=nothing, length::Union{Integer, Nothing}=nothing, step=nothing) =
257✔
153
    _range(start, step, stop, length)
154

155
_range(start::Nothing, step::Nothing, stop::Nothing, len::Nothing) = range_error(start, step, stop, len)
3✔
156
_range(start::Nothing, step::Nothing, stop::Nothing, len::Any    ) = range_length(len)
1✔
157
_range(start::Nothing, step::Nothing, stop::Any    , len::Nothing) = range_stop(stop)
2✔
158
_range(start::Nothing, step::Nothing, stop::Any    , len::Any    ) = range_stop_length(stop, len)
64✔
159
_range(start::Nothing, step::Any    , stop::Nothing, len::Nothing) = range_error(start, step, stop, len)
×
160
_range(start::Nothing, step::Any    , stop::Nothing, len::Any    ) = range_error(start, step, stop, len)
1✔
161
_range(start::Nothing, step::Any    , stop::Any    , len::Nothing) = range_error(start, step, stop, len)
1✔
162
_range(start::Nothing, step::Any    , stop::Any    , len::Any    ) = range_step_stop_length(step, stop, len)
10✔
163
_range(start::Any    , step::Nothing, stop::Nothing, len::Nothing) = range_error(start, step, stop, len)
1✔
164
_range(start::Any    , step::Nothing, stop::Nothing, len::Any    ) = range_start_length(start, len)
242✔
165
_range(start::Any    , step::Nothing, stop::Any    , len::Nothing) = range_start_stop(start, stop)
3,195,418✔
166
_range(start::Any    , step::Nothing, stop::Any    , len::Any    ) = range_start_stop_length(start, stop, len)
1,119,248✔
167
_range(start::Any    , step::Any    , stop::Nothing, len::Nothing) = range_error(start, step, stop, len)
1✔
168
_range(start::Any    , step::Any    , stop::Nothing, len::Any    ) = range_start_step_length(start, step, len)
26,586✔
169
_range(start::Any    , step::Any    , stop::Any    , len::Nothing) = range_start_step_stop(start, step, stop)
1,779✔
170
_range(start::Any    , step::Any    , stop::Any    , len::Any    ) = range_error(start, step, stop, len)
3✔
171

172
# Length as the only argument
173
range_length(len::Integer) = OneTo(len)
2✔
174

175
# Stop as the only argument
176
range_stop(stop) = range_start_stop(oftype(stop, 1), stop)
1✔
177
range_stop(stop::Integer) = range_length(stop)
1✔
178

179
function range_step_stop_length(step, a, len::Integer)
4✔
180
    start = a - step * (len - oneunit(len))
4✔
181
    if start isa Signed
4✔
182
        # overflow in recomputing length from stop is okay
183
        return StepRange{typeof(start),typeof(step)}(start, step, convert(typeof(start), a))
×
184
    end
185
    return StepRangeLen{typeof(start),typeof(start),typeof(step)}(start, step, len)
4✔
186
end
187

188
# Stop and length as the only argument
189
function range_stop_length(a, len::Integer)
9✔
190
    step = oftype(a - a, 1) # assert that step is representable
9✔
191
    start = a - (len - oneunit(len))
64✔
192
    if start isa Signed
9✔
193
        # overflow in recomputing length from stop is okay
194
        return UnitRange(start, oftype(start, a))
58✔
195
    end
196
    return StepRangeLen{typeof(start),typeof(start),typeof(step)}(start, step, len)
6✔
197
end
198

199
# Start and length as the only argument
200
function range_start_length(a, len::Integer)
209✔
201
    step = oftype(a - a, 1) # assert that step is representable
209✔
202
    stop = a + (len - oneunit(len))
210✔
203
    if stop isa Signed
208✔
204
        # overflow in recomputing length from stop is okay
205
        return UnitRange(oftype(stop, a), stop)
215✔
206
    end
207
    return StepRangeLen{typeof(stop),typeof(a),typeof(step)}(a, step, len)
26✔
208
end
209

210
range_start_stop(start, stop) = start:stop
3,195,419✔
211

212
function range_start_step_length(a, step, len::Integer)
26,550✔
213
    stop = a + step * (len - oneunit(len))
26,550✔
214
    if stop isa Signed
26,550✔
215
        # overflow in recomputing length from stop is okay
216
        return StepRange{typeof(stop),typeof(step)}(convert(typeof(stop), a), step, stop)
26,520✔
217
    end
218
    return StepRangeLen{typeof(stop),typeof(a),typeof(step)}(a, step, len)
30✔
219
end
220

221
range_start_step_stop(start, step, stop) = start:step:stop
1,779✔
222

223
function range_error(start, step, stop, length)
10✔
224
    hasstart  = start !== nothing
10✔
225
    hasstep   = step  !== nothing
10✔
226
    hasstop   = stop  !== nothing
10✔
227
    haslength = start !== nothing
10✔
228

229
    hint = if hasstart && hasstep && hasstop && haslength
10✔
230
        "Try specifying only three arguments"
3✔
231
    elseif !hasstop && !haslength
7✔
232
        "At least one of `length` or `stop` must be specified."
4✔
233
    elseif !hasstep && !haslength
3✔
234
        "At least one of `length` or `step` must be specified."
×
235
    elseif !hasstart && !hasstop
3✔
236
        "At least one of `start` or `stop` must be specified."
×
237
    else
238
        "Try specifying more arguments."
10✔
239
    end
240

241
    msg = """
10✔
242
    Cannot construct range from arguments:
243
    start = $start
244
    step = $step
245
    stop = $stop
246
    length = $length
247
    $hint
248
    """
249
    throw(ArgumentError(msg))
10✔
250
end
251

252
## 1-dimensional ranges ##
253

254
"""
255
    AbstractRange{T}
256

257
Supertype for ranges with elements of type `T`.
258
[`UnitRange`](@ref) and other types are subtypes of this.
259
"""
260
abstract type AbstractRange{T} <: AbstractArray{T,1} end
261

262
RangeStepStyle(::Type{<:AbstractRange}) = RangeStepIrregular()
×
263
RangeStepStyle(::Type{<:AbstractRange{<:Integer}}) = RangeStepRegular()
×
264

265
convert(::Type{T}, r::AbstractRange) where {T<:AbstractRange} = r isa T ? r : T(r)::T
89,191,499✔
266

267
## ordinal ranges
268

269
"""
270
    OrdinalRange{T, S} <: AbstractRange{T}
271

272
Supertype for ordinal ranges with elements of type `T` with
273
spacing(s) of type `S`. The steps should be always-exact
274
multiples of [`oneunit`](@ref), and `T` should be a "discrete"
275
type, which cannot have values smaller than `oneunit`. For example,
276
`Integer` or `Date` types would qualify, whereas `Float64` would not (since this
277
type can represent values smaller than `oneunit(Float64)`.
278
[`UnitRange`](@ref), [`StepRange`](@ref), and other types are subtypes of this.
279
"""
280
abstract type OrdinalRange{T,S} <: AbstractRange{T} end
281

282
"""
283
    AbstractUnitRange{T} <: OrdinalRange{T, T}
284

285
Supertype for ranges with a step size of [`oneunit(T)`](@ref) with elements of type `T`.
286
[`UnitRange`](@ref) and other types are subtypes of this.
287
"""
288
abstract type AbstractUnitRange{T} <: OrdinalRange{T,T} end
289

290
"""
291
    StepRange{T, S} <: OrdinalRange{T, S}
292

293
Ranges with elements of type `T` with spacing of type `S`. The step
294
between each element is constant, and the range is defined in terms
295
of a `start` and `stop` of type `T` and a `step` of type `S`. Neither
296
`T` nor `S` should be floating point types. The syntax `a:b:c` with `b != 0`
297
and `a`, `b`, and `c` all integers creates a `StepRange`.
298

299
# Examples
300
```jldoctest
301
julia> collect(StepRange(1, Int8(2), 10))
302
5-element Vector{Int64}:
303
 1
304
 3
305
 5
306
 7
307
 9
308

309
julia> typeof(StepRange(1, Int8(2), 10))
310
StepRange{Int64, Int8}
311

312
julia> typeof(1:3:6)
313
StepRange{Int64, Int64}
314
```
315
"""
316
struct StepRange{T,S} <: OrdinalRange{T,S}
317
    start::T
318
    step::S
319
    stop::T
320

321
    function StepRange{T,S}(start, step, stop) where {T,S}
2,076✔
322
        start = convert(T, start)
2,041✔
323
        step = convert(S, step)
2,041✔
324
        stop = convert(T, stop)
2,041✔
325
        return new(start, step, steprange_last(start, step, stop))
130,256,724✔
326
    end
327
end
328

329
# to make StepRange constructor inlineable, so optimizer can see `step` value
330
function steprange_last(start, step, stop)::typeof(stop)
130,256,446✔
331
    if isa(start, AbstractFloat) || isa(step, AbstractFloat)
1,987✔
332
        throw(ArgumentError("StepRange should not be used with floating point"))
1✔
333
    end
334
    if isa(start, Integer) && !isinteger(start + step)
130,256,389✔
335
        throw(ArgumentError("StepRange{<:Integer} cannot have non-integer step"))
1✔
336
    end
337
    z = zero(step)
1,985✔
338
    step == z && throw(ArgumentError("step cannot be zero"))
130,256,434✔
339

340
    if stop == start
130,256,431✔
341
        last = stop
6,396,339✔
342
    else
343
        if (step > z) != (stop > start)
123,860,362✔
344
            last = steprange_last_empty(start, step, stop)
25,324,027✔
345
        else
346
            # Compute absolute value of difference between `start` and `stop`
347
            # (to simplify handling both signed and unsigned T and checking for signed overflow):
348
            absdiff, absstep = stop > start ? (stop - start, step) : (start - stop, -step)
193,938,959✔
349

350
            # Compute remainder as a nonnegative number:
351
            if absdiff isa Signed && absdiff < zero(absdiff)
98,536,065✔
352
                # unlikely, but handle the signed overflow case with unsigned rem
353
                remain = convert(typeof(absdiff), unsigned(absdiff) % absstep)
284✔
354
            else
355
                remain = convert(typeof(absdiff), absdiff % absstep)
98,535,781✔
356
            end
357
            # Move `stop` closer to `start` if there is a remainder:
358
            last = stop > start ? stop - remain : stop + remain
98,536,065✔
359
        end
360
    end
361
    return last
130,256,431✔
362
end
363

364
function steprange_last_empty(start::Integer, step, stop)::typeof(stop)
181✔
365
    # empty range has a special representation where stop = start-1,
366
    # which simplifies arithmetic for Signed numbers
367
    if step > zero(step)
25,324,023✔
368
        last = start - oneunit(step)
598,705✔
369
    else
370
        last = start + oneunit(step)
24,725,318✔
371
    end
372
    return last
25,324,023✔
373
end
374
# For types where x+oneunit(x) may not be well-defined use the user-given value for stop
375
steprange_last_empty(start, step, stop) = stop
4✔
376

377
StepRange{T}(start, step::S, stop) where {T,S} = StepRange{T,S}(start, step, stop)
33✔
378
StepRange(start::T, step::S, stop::T) where {T,S} = StepRange{T,S}(start, step, stop)
130,230,145✔
379

380
"""
381
    UnitRange{T<:Real}
382

383
A range parameterized by a `start` and `stop` of type `T`, filled
384
with elements spaced by `1` from `start` until `stop` is exceeded.
385
The syntax `a:b` with `a` and `b` both `Integer`s creates a `UnitRange`.
386

387
# Examples
388
```jldoctest
389
julia> collect(UnitRange(2.3, 5.2))
390
3-element Vector{Float64}:
391
 2.3
392
 3.3
393
 4.3
394

395
julia> typeof(1:10)
396
UnitRange{Int64}
397
```
398
"""
399
struct UnitRange{T<:Real} <: AbstractUnitRange{T}
400
    start::T
401
    stop::T
402
    UnitRange{T}(start::T, stop::T) where {T<:Real} = new(start, unitrange_last(start, stop))
2,412,361,337✔
403
end
404
UnitRange{T}(start, stop) where {T<:Real} = UnitRange{T}(convert(T, start), convert(T, stop))
229✔
405
UnitRange(start::T, stop::T) where {T<:Real} = UnitRange{T}(start, stop)
8,040✔
406
UnitRange(start, stop) = UnitRange(promote(start, stop)...)
×
407

408
# if stop and start are integral, we know that their difference is a multiple of 1
409
unitrange_last(start::Integer, stop::Integer) =
2,412,361,759✔
410
    stop >= start ? stop : convert(typeof(stop), start - oneunit(start - stop))
411
# otherwise, use `floor` as a more efficient way to compute modulus with step=1
412
unitrange_last(start, stop) =
10✔
413
    stop >= start ? convert(typeof(stop), start + floor(stop - start)) :
414
                    convert(typeof(stop), start - oneunit(start - stop))
415

416
unitrange(x::AbstractUnitRange) = UnitRange(x) # convenience conversion for promoting the range type
4,499✔
417

418
if isdefined(Main, :Base)
419
    # Constant-fold-able indexing into tuples to functionally expose Base.tail and Base.front
420
    function getindex(@nospecialize(t::Tuple), r::AbstractUnitRange)
200,246✔
421
        @inline
193,677✔
422
        require_one_based_indexing(r)
193,678✔
423
        if length(r) <= 10
200,302✔
424
            return ntuple(i -> t[i + first(r) - 1], length(r))
605,656✔
425
        elseif first(r) == 1
5✔
426
            last(r) == length(t)   && return t
3✔
427
            last(r) == length(t)-1 && return front(t)
2✔
428
            last(r) == length(t)-2 && return front(front(t))
1✔
429
        elseif last(r) == length(t)
2✔
430
            first(r) == 2 && return tail(t)
2✔
431
            first(r) == 3 && return tail(tail(t))
1✔
432
        end
433
        return (eltype(t)[t[ri] for ri in r]...,)
×
434
    end
435
end
436

437
"""
438
    Base.OneTo(n)
439

440
Define an `AbstractUnitRange` that behaves like `1:n`, with the added
441
distinction that the lower limit is guaranteed (by the type system) to
442
be 1.
443
"""
444
struct OneTo{T<:Integer} <: AbstractUnitRange{T}
445
    stop::T
446
    function OneTo{T}(stop) where {T<:Integer}
14,621✔
447
        throwbool(r)  = (@noinline; throw(ArgumentError("invalid index: $r of type Bool")))
14,619✔
448
        T === Bool && throwbool(stop)
14,618✔
449
        return new(max(zero(T), stop))
5,339,517,229✔
450
    end
451

452
    function OneTo{T}(r::AbstractRange) where {T<:Integer}
77,856,112✔
453
        throwstart(r) = (@noinline; throw(ArgumentError("first element must be 1, got $(first(r))")))
77,856,113✔
454
        throwstep(r)  = (@noinline; throw(ArgumentError("step must be 1, got $(step(r))")))
77,856,110✔
455
        throwbool(r)  = (@noinline; throw(ArgumentError("invalid index: $r of type Bool")))
77,856,110✔
456
        first(r) == 1 || throwstart(r)
77,856,113✔
457
        step(r)  == 1 || throwstep(r)
77,856,110✔
458
        T === Bool && throwbool(r)
77,856,108✔
459
        return new(max(zero(T), last(r)))
78,078,947✔
460
    end
461
end
462
OneTo(stop::T) where {T<:Integer} = OneTo{T}(stop)
5,339,503,843✔
463
OneTo(r::AbstractRange{T}) where {T<:Integer} = OneTo{T}(r)
9✔
464
oneto(r) = OneTo(r)
5,341,020,522✔
465

466
## Step ranges parameterized by length
467

468
"""
469
    StepRangeLen(         ref::R, step::S, len, [offset=1]) where {  R,S}
470
    StepRangeLen{T,R,S}(  ref::R, step::S, len, [offset=1]) where {T,R,S}
471
    StepRangeLen{T,R,S,L}(ref::R, step::S, len, [offset=1]) where {T,R,S,L}
472

473
A range `r` where `r[i]` produces values of type `T` (in the first
474
form, `T` is deduced automatically), parameterized by a `ref`erence
475
value, a `step`, and the `len`gth. By default `ref` is the starting
476
value `r[1]`, but alternatively you can supply it as the value of
477
`r[offset]` for some other index `1 <= offset <= len`. The syntax `a:b`
478
or `a:b:c`, where any of `a`, `b`, or `c` are floating-point numbers, creates a
479
`StepRangeLen`.
480
In conjunction with `TwicePrecision` this can be used to implement ranges that
481
are free of roundoff error.
482

483
!!! compat "Julia 1.7"
484
    The 4th type parameter `L` requires at least Julia 1.7.
485
"""
486
struct StepRangeLen{T,R,S,L<:Integer} <: AbstractRange{T}
487
    ref::R       # reference value (might be smallest-magnitude value in the range)
488
    step::S      # step value
489
    len::L       # length of the range
490
    offset::L    # the index of ref
491

492
    function StepRangeLen{T,R,S,L}(ref::R, step::S, len::Integer, offset::Integer = 1) where {T,R,S,L}
6,984,291✔
493
        if T <: Integer && !isinteger(ref + step)
6,984,291✔
494
            throw(ArgumentError("StepRangeLen{<:Integer} cannot have non-integer step"))
1✔
495
        end
496
        len = convert(L, len)
6,984,162✔
497
        len >= zero(len) || throw(ArgumentError("length cannot be negative, got $len"))
6,984,162✔
498
        offset = convert(L, offset)
6,984,162✔
499
        L1 = oneunit(typeof(len))
6,984,162✔
500
        L1 <= offset <= max(L1, len) || throw(ArgumentError("StepRangeLen: offset must be in [1,$len], got $offset"))
6,984,162✔
501
        return new(ref, step, len, offset)
6,984,162✔
502
    end
503
end
504

505
StepRangeLen{T,R,S}(ref::R, step::S, len::Integer, offset::Integer = 1) where {T,R,S} =
1,121,315✔
506
    StepRangeLen{T,R,S,promote_type(Int,typeof(len))}(ref, step, len, offset)
507
StepRangeLen(ref::R, step::S, len::Integer, offset::Integer = 1) where {R,S} =
1,181✔
508
    StepRangeLen{typeof(ref+zero(step)),R,S,promote_type(Int,typeof(len))}(ref, step, len, offset)
509
StepRangeLen{T}(ref::R, step::S, len::Integer, offset::Integer = 1) where {T,R,S} =
5,862,046✔
510
    StepRangeLen{T,R,S,promote_type(Int,typeof(len))}(ref, step, len, offset)
511

512
## range with computed step
513

514
"""
515
    LinRange{T,L}
516

517
A range with `len` linearly spaced elements between its `start` and `stop`.
518
The size of the spacing is controlled by `len`, which must
519
be an `Integer`.
520

521
# Examples
522
```jldoctest
523
julia> LinRange(1.5, 5.5, 9)
524
9-element LinRange{Float64, Int64}:
525
 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5
526
```
527

528
Compared to using [`range`](@ref), directly constructing a `LinRange` should
529
have less overhead but won't try to correct for floating point errors:
530
```jldoctest
531
julia> collect(range(-0.1, 0.3, length=5))
532
5-element Vector{Float64}:
533
 -0.1
534
  0.0
535
  0.1
536
  0.2
537
  0.3
538

539
julia> collect(LinRange(-0.1, 0.3, 5))
540
5-element Vector{Float64}:
541
 -0.1
542
 -1.3877787807814457e-17
543
  0.09999999999999999
544
  0.19999999999999998
545
  0.3
546
```
547
"""
548
struct LinRange{T,L<:Integer} <: AbstractRange{T}
549
    start::T
550
    stop::T
551
    len::L
552
    lendiv::L
553

554
    function LinRange{T,L}(start::T, stop::T, len::L) where {T,L<:Integer}
128✔
555
        len >= 0 || throw(ArgumentError("range($start, stop=$stop, length=$len): negative length"))
128✔
556
        onelen = oneunit(typeof(len))
128✔
557
        if len == onelen
128✔
558
            start == stop || throw(ArgumentError("range($start, stop=$stop, length=$len): endpoints differ"))
8✔
559
            return new(start, stop, len, len)
8✔
560
        end
561
        lendiv = max(len - onelen, onelen)
120✔
562
        if T <: Integer && !iszero(mod(stop-start, lendiv))
137✔
563
            throw(ArgumentError("LinRange{<:Integer} cannot have non-integer step"))
1✔
564
        end
565
        return new(start, stop, len, lendiv)
119✔
566
    end
567
end
568

569
function LinRange{T,L}(start, stop, len::Integer) where {T,L}
60✔
570
    LinRange{T,L}(convert(T, start), convert(T, stop), convert(L, len))
60✔
571
end
572

573
function LinRange{T}(start, stop, len::Integer) where T
115✔
574
    LinRange{T,promote_type(Int,typeof(len))}(start, stop, len)
115✔
575
end
576

577
function LinRange(start, stop, len::Integer)
79✔
578
    T = typeof((zero(stop) - zero(start)) / oneunit(len))
88✔
579
    LinRange{T}(start, stop, len)
79✔
580
end
581

582
range_start_stop_length(start, stop, len::Integer) =
16✔
583
    range_start_stop_length(promote(start, stop)..., len)
584
range_start_stop_length(start::T, stop::T, len::Integer) where {T} = LinRange(start, stop, len)
15✔
585
range_start_stop_length(start::T, stop::T, len::Integer) where {T<:Integer} =
175✔
586
    _linspace(float(T), start, stop, len)
587
## for Float16, Float32, and Float64 we hit twiceprecision.jl to lift to higher precision StepRangeLen
588
# for all other types we fall back to a plain old LinRange
589
_linspace(::Type{T}, start::Integer, stop::Integer, len::Integer) where T = LinRange{T}(start, stop, len)
4✔
590

591
function show(io::IO, r::LinRange{T}) where {T}
1✔
592
    print(io, "LinRange{")
1✔
593
    show(io, T)
1✔
594
    print(io, "}(")
1✔
595
    ioc = IOContext(io, :typeinto=>T)
1✔
596
    show(ioc, first(r))
1✔
597
    print(io, ", ")
1✔
598
    show(ioc, last(r))
1✔
599
    print(io, ", ")
1✔
600
    show(io, length(r))
1✔
601
    print(io, ')')
1✔
602
end
603

604
"""
605
`print_range(io, r)` prints out a nice looking range r in terms of its elements
606
as if it were `collect(r)`, dependent on the size of the
607
terminal, and taking into account whether compact numbers should be shown.
608
It figures out the width in characters of each element, and if they
609
end up too wide, it shows the first and last elements separated by a
610
horizontal ellipsis. Typical output will look like `1.0, 2.0, …, 5.0, 6.0`.
611

612
`print_range(io, r, pre, sep, post, hdots)` uses optional
613
parameters `pre` and `post` characters for each printed row,
614
`sep` separator string between printed elements,
615
`hdots` string for the horizontal ellipsis.
616
"""
617
function print_range(io::IO, r::AbstractRange,
4✔
618
                     pre::AbstractString = " ",
619
                     sep::AbstractString = ", ",
620
                     post::AbstractString = "",
621
                     hdots::AbstractString = ", \u2026, ") # horiz ellipsis
622
    # This function borrows from print_matrix() in show.jl
623
    # and should be called by show and display
624
    sz = displaysize(io)
4✔
625
    if !haskey(io, :compact)
4✔
626
        io = IOContext(io, :compact => true)
2✔
627
    end
628
    screenheight, screenwidth = sz[1] - 4, sz[2]
2✔
629
    screenwidth -= length(pre) + length(post)
2✔
630
    postsp = ""
2✔
631
    sepsize = length(sep)
2✔
632
    m = 1 # treat the range as a one-row matrix
2✔
633
    n = length(r)
2✔
634
    # Figure out spacing alignments for r, but only need to examine the
635
    # left and right edge columns, as many as could conceivably fit on the
636
    # screen, with the middle columns summarized by horz, vert, or diag ellipsis
637
    maxpossiblecols = div(screenwidth, 1+sepsize) # assume each element is at least 1 char + 1 separator
2✔
638
    colsr = n <= maxpossiblecols ? (1:n) : [1:div(maxpossiblecols,2)+1; (n-div(maxpossiblecols,2)):n]
2✔
639
    rowmatrix = reshape(r[colsr], 1, length(colsr)) # treat the range as a one-row matrix for print_matrix_row
2✔
640
    nrow, idxlast = size(rowmatrix, 2), last(axes(rowmatrix, 2))
3✔
641
    A = alignment(io, rowmatrix, 1:m, 1:length(rowmatrix), screenwidth, screenwidth, sepsize, nrow) # how much space range takes
3✔
642
    if n <= length(A) # cols fit screen, so print out all elements
2✔
643
        print(io, pre) # put in pre chars
1✔
644
        print_matrix_row(io,rowmatrix,A,1,1:n,sep,idxlast) # the entire range
1✔
645
        print(io, post) # add the post characters
1✔
646
    else # cols don't fit so put horiz ellipsis in the middle
647
        # how many chars left after dividing width of screen in half
648
        # and accounting for the horiz ellipsis
649
        c = div(screenwidth-length(hdots)+1,2)+1 # chars remaining for each side of rowmatrix
1✔
650
        alignR = reverse(alignment(io, rowmatrix, 1:m, length(rowmatrix):-1:1, c, c, sepsize, nrow)) # which cols of rowmatrix to put on the right
2✔
651
        c = screenwidth - sum(map(sum,alignR)) - (length(alignR)-1)*sepsize - length(hdots)
2✔
652
        alignL = alignment(io, rowmatrix, 1:m, 1:length(rowmatrix), c, c, sepsize, nrow) # which cols of rowmatrix to put on the left
2✔
653
        print(io, pre)   # put in pre chars
1✔
654
        print_matrix_row(io, rowmatrix,alignL,1,1:length(alignL),sep,idxlast) # left part of range
2✔
655
        print(io, hdots) # horizontal ellipsis
1✔
656
        print_matrix_row(io, rowmatrix,alignR,1,length(rowmatrix)-length(alignR)+1:length(rowmatrix),sep,idxlast) # right part of range
2✔
657
        print(io, post)  # post chars
1✔
658
    end
659
end
660

661
## interface implementations
662

663
length(r::AbstractRange) = error("length implementation missing") # catch mistakes
×
664
size(r::AbstractRange) = (length(r),)
2,433✔
665

666
isempty(r::StepRange) =
145,480,975✔
667
    # steprange_last(r.start, r.step, r.stop) == r.stop
668
    (r.start != r.stop) & ((r.step > zero(r.step)) != (r.stop > r.start))
669
isempty(r::AbstractUnitRange) = first(r) > last(r)
2,758,868,670✔
670
isempty(r::StepRangeLen) = length(r) == 0
1,432✔
671
isempty(r::LinRange) = length(r) == 0
37✔
672

673
"""
674
    step(r)
675

676
Get the step size of an [`AbstractRange`](@ref) object.
677

678
# Examples
679
```jldoctest
680
julia> step(1:10)
681
1
682

683
julia> step(1:2:10)
684
2
685

686
julia> step(2.5:0.3:10.9)
687
0.3
688

689
julia> step(range(2.5, stop=10.9, length=85))
690
0.1
691
```
692
"""
693
step(r::StepRange) = r.step
53,812,684✔
694
step(r::AbstractUnitRange{T}) where {T} = oneunit(T) - zero(T)
26,714,674,239✔
695
step(r::StepRangeLen) = r.step
185✔
696
step(r::StepRangeLen{T}) where {T<:AbstractFloat} = T(r.step)
165,098✔
697
step(r::LinRange) = (last(r)-first(r))/r.lendiv
26✔
698

699
# high-precision step
700
step_hp(r::StepRangeLen) = r.step
4,743,036✔
701
step_hp(r::AbstractRange) = step(r)
15,419,489✔
702

703
axes(r::AbstractRange) = (oneto(length(r)),)
705,056,334✔
704

705
# Needed to ensure `has_offset_axes` can constant-fold.
706
has_offset_axes(::StepRange) = false
794,345✔
707

708
# n.b. checked_length for these is defined iff checked_add and checked_sub are
709
# defined between the relevant types
710
function checked_length(r::OrdinalRange{T}) where T
12✔
711
    s = step(r)
12✔
712
    start = first(r)
12✔
713
    if isempty(r)
12✔
714
        return Integer(div(start - start, oneunit(s)))
2✔
715
    end
716
    stop = last(r)
10✔
717
    if isless(s, zero(s))
10✔
718
        diff = checked_sub(start, stop)
2✔
719
        s = -s
2✔
720
    else
721
        diff = checked_sub(stop, start)
8✔
722
    end
723
    a = div(diff, s)
8✔
724
    return Integer(checked_add(a, oneunit(a)))
8✔
725
end
726

727
function checked_length(r::AbstractUnitRange{T}) where T
30✔
728
    # compiler optimization: remove dead cases from above
729
    if isempty(r)
30✔
730
        return Integer(first(r) - first(r))
3✔
731
    end
732
    a = checked_sub(last(r), first(r))
27✔
733
    return Integer(checked_add(a, oneunit(a)))
22✔
734
end
735

736
function length(r::OrdinalRange{T}) where T
2,070✔
737
    s = step(r)
2,070✔
738
    start = first(r)
2,070✔
739
    if isempty(r)
2,440✔
740
        return Integer(div(start - start, oneunit(s)))
327✔
741
    end
742
    stop = last(r)
1,743✔
743
    if isless(s, zero(s))
2,357✔
744
        diff = start - stop
147✔
745
        s = -s
147✔
746
    else
747
        diff = stop - start
1,596✔
748
    end
749
    a = div(diff, s)
1,743✔
750
    return Integer(a + oneunit(a))
1,743✔
751
end
752

753
function length(r::AbstractUnitRange{T}) where T
10,133,495✔
754
    @inline
3,808✔
755
    start, stop = first(r), last(r)
79,281,570✔
756
    a = oneunit(zero(stop) - zero(start))
3,808✔
757
    if a isa Signed || stop >= start
286,818✔
758
        a += stop - start # Signed are allowed to go negative
606,838,515✔
759
    else
760
        a = zero(a) # Unsigned don't necessarily underflow
4✔
761
    end
762
    return Integer(a)
291,130✔
763
end
764

765
length(r::OneTo) = Integer(r.stop - zero(r.stop))
27✔
766
length(r::StepRangeLen) = r.len
108,744,798✔
767
length(r::LinRange) = r.len
6,032✔
768

769
let bigints = Union{Int, UInt, Int64, UInt64, Int128, UInt128},
770
    smallints = (Int === Int64 ?
771
                Union{Int8, UInt8, Int16, UInt16, Int32, UInt32} :
772
                Union{Int8, UInt8, Int16, UInt16}),
773
    bitints = Union{bigints, smallints}
774
    global length, checked_length, firstindex
775
    # compile optimization for which promote_type(T, Int) == T
776
    length(r::OneTo{T}) where {T<:bigints} = r.stop
92,752,079✔
777
    # slightly more accurate length and checked_length in extreme cases
778
    # (near typemax) for types with known `unsigned` functions
779
    function length(r::OrdinalRange{T}) where T<:bigints
15,994,738✔
780
        s = step(r)
15,994,738✔
781
        diff = last(r) - first(r)
15,994,744✔
782
        isempty(r) && return zero(diff)
15,994,744✔
783
        # if |s| > 1, diff might have overflowed, but unsigned(diff)÷s should
784
        # therefore still be valid (if the result is representable at all)
785
        # n.b. !(s isa T)
786
        if s isa Unsigned || -1 <= s <= 1 || s == -s
26,827,520✔
787
            a = div(diff, s) % typeof(diff)
2,277,831✔
788
        elseif s < 0
12,274,898✔
789
            a = div(unsigned(-diff), -s) % typeof(diff)
2,456,600✔
790
        else
791
            a = div(unsigned(diff), s) % typeof(diff)
9,818,298✔
792
        end
793
        return a + oneunit(a)
14,552,728✔
794
    end
795
    function checked_length(r::OrdinalRange{T}) where T<:bigints
229✔
796
        s = step(r)
229✔
797
        stop, start = last(r), first(r)
233✔
798
        ET = promote_type(typeof(stop), typeof(start))
233✔
799
        isempty(r) && return zero(ET)
233✔
800
        # n.b. !(s isa T)
801
        if s > 1
221✔
802
            diff = stop - start
101✔
803
            a = convert(ET, div(unsigned(diff), s))
101✔
804
        elseif s < -1
120✔
805
            diff = start - stop
106✔
806
            a = convert(ET, div(unsigned(diff), -s))
106✔
807
        elseif s > 0
14✔
808
            a = convert(ET, div(checked_sub(stop, start), s))
13✔
809
        else
810
            a = convert(ET, div(checked_sub(start, stop), -s))
1✔
811
        end
812
        return checked_add(a, oneunit(a))
213✔
813
    end
814
    firstindex(r::StepRange{<:bigints,<:bitints}) = one(last(r)-first(r))
57,892✔
815

816
    # some special cases to favor default Int type
817
    function length(r::OrdinalRange{<:smallints})
450✔
818
        s = step(r)
450✔
819
        isempty(r) && return 0
450✔
820
        # n.b. !(step isa T)
821
        return Int(div(Int(last(r)) - Int(first(r)), s)) + 1
364✔
822
    end
823
    length(r::AbstractUnitRange{<:smallints}) = Int(last(r)) - Int(first(r)) + 1
294,848✔
824
    length(r::OneTo{<:smallints}) = Int(r.stop)
2,495✔
825
    checked_length(r::OrdinalRange{<:smallints}) = length(r)
20✔
826
    checked_length(r::AbstractUnitRange{<:smallints}) = length(r)
6✔
827
    checked_length(r::OneTo{<:smallints}) = length(r)
×
828
    firstindex(::StepRange{<:smallints,<:bitints}) = 1
126✔
829
end
830

831
first(r::OrdinalRange{T}) where {T} = convert(T, r.start)
139,016,302✔
832
first(r::OneTo{T}) where {T} = oneunit(T)
282,249✔
833
first(r::StepRangeLen) = unsafe_getindex(r, 1)
660,192✔
834
first(r::LinRange) = r.start
82✔
835

836
last(r::OrdinalRange{T}) where {T} = convert(T, r.stop) # via steprange_last
27,159,282,165✔
837
last(r::StepRangeLen) = unsafe_getindex(r, length(r))
660,020✔
838
last(r::LinRange) = r.stop
64✔
839

840
minimum(r::AbstractUnitRange) = isempty(r) ? throw(ArgumentError("range must be non-empty")) : first(r)
6,645,395✔
841
maximum(r::AbstractUnitRange) = isempty(r) ? throw(ArgumentError("range must be non-empty")) : last(r)
6,645,265✔
842
minimum(r::AbstractRange)  = isempty(r) ? throw(ArgumentError("range must be non-empty")) : min(first(r), last(r))
3,283✔
843
maximum(r::AbstractRange)  = isempty(r) ? throw(ArgumentError("range must be non-empty")) : max(first(r), last(r))
3,160✔
844

845
"""
846
    argmin(r::AbstractRange)
847

848
Ranges can have multiple minimal elements. In that case
849
`argmin` will return a minimal index, but not necessarily the
850
first one.
851
"""
852
function argmin(r::AbstractRange)
10✔
853
    if isempty(r)
10✔
854
        throw(ArgumentError("range must be non-empty"))
1✔
855
    elseif step(r) > 0
9✔
856
        firstindex(r)
6✔
857
    else
858
        lastindex(r)
3✔
859
    end
860
end
861

862
"""
863
    argmax(r::AbstractRange)
864

865
Ranges can have multiple maximal elements. In that case
866
`argmax` will return a maximal index, but not necessarily the
867
first one.
868
"""
869
function argmax(r::AbstractRange)
11✔
870
    if isempty(r)
11✔
871
        throw(ArgumentError("range must be non-empty"))
1✔
872
    elseif step(r) > 0
10✔
873
        lastindex(r)
7✔
874
    else
875
        firstindex(r)
3✔
876
    end
877
end
878

879
extrema(r::AbstractRange) = (minimum(r), maximum(r))
320✔
880

881
# Ranges are immutable
882
copy(r::AbstractRange) = r
31✔
883

884

885
## iteration
886

887
function iterate(r::Union{StepRangeLen,LinRange}, i::Integer=zero(length(r)))
89,943,516✔
888
    @inline
89,943,516✔
889
    i += oneunit(i)
99,571,760✔
890
    length(r) < i && return nothing
78,872,166✔
891
    unsafe_getindex(r, i), i
67,801,002✔
892
end
893

894
iterate(r::OrdinalRange) = isempty(r) ? nothing : (first(r), first(r))
4,361,978,236✔
895

896
function iterate(r::OrdinalRange{T}, i) where {T}
53,156,066,301✔
897
    @inline
26,713,415,359✔
898
    i == last(r) && return nothing
68,351,723,495✔
899
    next = convert(T, i + step(r))
66,712,030,784✔
900
    (next, next)
66,718,070,690✔
901
end
902

903
## indexing
904

905
_in_unit_range(v::UnitRange, val, i::Integer) = i > 0 && val <= v.stop && val >= v.start
207,178,399✔
906

907
function getindex(v::UnitRange{T}, i::Integer) where T
288✔
908
    @inline
288✔
909
    i isa Bool && throw(ArgumentError("invalid index: $i of type Bool"))
288✔
910
    val = convert(T, v.start + (i - oneunit(i)))
289✔
911
    @boundscheck _in_unit_range(v, val, i) || throw_boundserror(v, i)
287✔
912
    val
287✔
913
end
914

915
const OverflowSafe = Union{Bool,Int8,Int16,Int32,Int64,Int128,
916
                           UInt8,UInt16,UInt32,UInt64,UInt128}
917

918
function getindex(v::UnitRange{T}, i::Integer) where {T<:OverflowSafe}
9,241,617✔
919
    @inline
9,241,132✔
920
    i isa Bool && throw(ArgumentError("invalid index: $i of type Bool"))
9,241,255✔
921
    val = v.start + (i - oneunit(i))
676,089,474✔
922
    @boundscheck _in_unit_range(v, val, i) || throw_boundserror(v, i)
672,549,195✔
923
    val % T
671,192,733✔
924
end
925

926
function getindex(v::OneTo{T}, i::Integer) where T
5,563,933✔
927
    @inline
5,563,924✔
928
    i isa Bool && throw(ArgumentError("invalid index: $i of type Bool"))
5,563,924✔
929
    @boundscheck ((i > 0) & (i <= v.stop)) || throw_boundserror(v, i)
79,381,896✔
930
    convert(T, i)
79,381,891✔
931
end
932

933
function getindex(v::AbstractRange{T}, i::Integer) where T
10,652,216✔
934
    @inline
10,652,216✔
935
    i isa Bool && throw(ArgumentError("invalid index: $i of type Bool"))
10,652,216✔
936
    ret = convert(T, first(v) + (i - oneunit(i))*step_hp(v))
10,677,596✔
937
    ok = ifelse(step(v) > zero(step(v)),
10,676,544✔
938
                (ret <= last(v)) & (ret >= first(v)),
939
                (ret <= first(v)) & (ret >= last(v)))
940
    @boundscheck ((i > 0) & ok) || throw_boundserror(v, i)
10,676,453✔
941
    ret
10,676,453✔
942
end
943

944
function getindex(r::Union{StepRangeLen,LinRange}, i::Integer)
79,574✔
945
    @inline
79,574✔
946
    i isa Bool && throw(ArgumentError("invalid index: $i of type Bool"))
79,574✔
947
    @boundscheck checkbounds(r, i)
79,572✔
948
    unsafe_getindex(r, i)
79,877✔
949
end
950

951
# This is separate to make it useful even when running with --check-bounds=yes
952
function unsafe_getindex(r::StepRangeLen{T}, i::Integer) where T
34,506,496✔
953
    i isa Bool && throw(ArgumentError("invalid index: $i of type Bool"))
34,506,496✔
954
    u = i - r.offset
34,507,106✔
955
    T(r.ref + u*r.step)
34,506,496✔
956
end
957

958
function _getindex_hiprec(r::StepRangeLen, i::Integer)  # without rounding by T
2,371,508✔
959
    i isa Bool && throw(ArgumentError("invalid index: $i of type Bool"))
2,371,508✔
960
    u = i - r.offset
2,371,508✔
961
    r.ref + u*r.step
2,371,508✔
962
end
963

964
function unsafe_getindex(r::LinRange, i::Integer)
3,753✔
965
    i isa Bool && throw(ArgumentError("invalid index: $i of type Bool"))
3,753✔
966
    lerpi(i-oneunit(i), r.lendiv, r.start, r.stop)
3,753✔
967
end
968

969
function lerpi(j::Integer, d::Integer, a::T, b::T) where T
3,659✔
970
    @inline
3,659✔
971
    t = j/d # ∈ [0,1]
3,659✔
972
    # compute approximately fma(t, b, -fma(t, a, a))
973
    return T((1-t)*a + t*b)
3,659✔
974
end
975

976
getindex(r::AbstractRange, ::Colon) = copy(r)
27✔
977

978
function getindex(r::AbstractUnitRange, s::AbstractUnitRange{T}) where {T<:Integer}
132,359✔
979
    @inline
128,005✔
980
    @boundscheck checkbounds(r, s)
152,851✔
981

982
    if T === Bool
127,999✔
983
        return range(first(s) ? first(r) : last(r), length = last(s))
10✔
984
    else
985
        f = first(r)
132,990✔
986
        start = oftype(f, f + first(s) - firstindex(r))
151,150✔
987
        len = length(s)
152,323✔
988
        stop = oftype(f, start + (len - oneunit(len)))
152,325✔
989
        return range(start, stop)
152,955✔
990
    end
991
end
992

993
function getindex(r::OneTo{T}, s::OneTo) where T
10✔
994
    @inline
10✔
995
    @boundscheck checkbounds(r, s)
10✔
996
    return OneTo(T(s.stop))
10✔
997
end
998

999
function getindex(r::AbstractUnitRange, s::StepRange{T}) where {T<:Integer}
29✔
1000
    @inline
29✔
1001
    @boundscheck checkbounds(r, s)
36✔
1002

1003
    if T === Bool
22✔
1004
        return range(first(s) ? first(r) : last(r), step=oneunit(eltype(r)), length=last(s))
9✔
1005
    else
1006
        f = first(r)
15✔
1007
        start = oftype(f, f + s.start - firstindex(r))
15✔
1008
        st = step(s)
15✔
1009
        len = length(s)
15✔
1010
        stop = oftype(f, start + (len - oneunit(len)) * st)
15✔
1011
        return range(start, stop; step=st)
15✔
1012
    end
1013
end
1014

1015
function getindex(r::StepRange, s::AbstractRange{T}) where {T<:Integer}
1,663✔
1016
    @inline
1,663✔
1017
    @boundscheck checkbounds(r, s)
1,671✔
1018

1019
    if T === Bool
1,655✔
1020
        if length(s) == 0
10✔
1021
            start, len = first(r), 0
1✔
1022
        elseif length(s) == 1
9✔
1023
            if first(s)
6✔
1024
                start, len = first(r), 1
3✔
1025
            else
1026
                start, len = first(r), 0
6✔
1027
            end
1028
        else # length(s) == 2
1029
            start, len = last(r), 1
3✔
1030
        end
1031
        return range(start, step=step(r); length=len)
10✔
1032
    else
1033
        f = r.start
1,645✔
1034
        fs = first(s)
1,645✔
1035
        st = r.step
1,645✔
1036
        start = oftype(f, f + (fs - oneunit(fs)) * st)
1,647✔
1037
        st = st * step(s)
1,645✔
1038
        len = length(s)
1,645✔
1039
        stop = oftype(f, start + (len - oneunit(len)) * st)
1,647✔
1040
        return range(start, stop; step=st)
1,645✔
1041
    end
1042
end
1043

1044
function getindex(r::StepRangeLen{T}, s::OrdinalRange{S}) where {T, S<:Integer}
2,371,517✔
1045
    @inline
2,371,517✔
1046
    @boundscheck checkbounds(r, s)
2,371,522✔
1047

1048
    len = length(s)
2,371,512✔
1049
    sstep = step_hp(s)
2,371,512✔
1050
    rstep = step_hp(r)
2,371,512✔
1051
    L = typeof(len)
2,371,512✔
1052
    if S === Bool
2,371,512✔
1053
        rstep *= one(sstep)
4✔
1054
        if len == 0
4✔
1055
            return StepRangeLen{T}(first(r), rstep, zero(L), oneunit(L))
1✔
1056
        elseif len == 1
3✔
1057
            if first(s)
2✔
1058
                return StepRangeLen{T}(first(r), rstep, oneunit(L), oneunit(L))
1✔
1059
            else
1060
                return StepRangeLen{T}(first(r), rstep, zero(L), oneunit(L))
1✔
1061
            end
1062
        else # len == 2
1063
            return StepRangeLen{T}(last(r), rstep, oneunit(L), oneunit(L))
1✔
1064
        end
1065
    else
1066
        # Find closest approach to offset by s
1067
        ind = LinearIndices(s)
2,371,508✔
1068
        offset = L(max(min(1 + round(L, (r.offset - first(s))/sstep), last(ind)), first(ind)))
2,371,508✔
1069
        ref = _getindex_hiprec(r, first(s) + (offset - oneunit(offset)) * sstep)
2,371,508✔
1070
        return StepRangeLen{T}(ref, rstep*sstep, len, offset)
2,371,508✔
1071
    end
1072
end
1073

1074
function getindex(r::LinRange{T}, s::OrdinalRange{S}) where {T, S<:Integer}
17✔
1075
    @inline
17✔
1076
    @boundscheck checkbounds(r, s)
22✔
1077

1078
    len = length(s)
12✔
1079
    L = typeof(len)
12✔
1080
    if S === Bool
12✔
1081
        if len == 0
4✔
1082
            return LinRange{T}(first(r), first(r), len)
1✔
1083
        elseif len == 1
3✔
1084
            if first(s)
2✔
1085
                return LinRange{T}(first(r), first(r), len)
1✔
1086
            else
1087
                return LinRange{T}(first(r), first(r), zero(L))
1✔
1088
            end
1089
        else # length(s) == 2
1090
            return LinRange{T}(last(r), last(r), oneunit(L))
1✔
1091
        end
1092
    else
1093
        vfirst = unsafe_getindex(r, first(s))
8✔
1094
        vlast  = unsafe_getindex(r, last(s))
8✔
1095
        return LinRange{T}(vfirst, vlast, len)
8✔
1096
    end
1097
end
1098

1099
show(io::IO, r::AbstractRange) = print(io, repr(first(r)), ':', repr(step(r)), ':', repr(last(r)))
5✔
1100
show(io::IO, r::UnitRange) = print(io, repr(first(r)), ':', repr(last(r)))
117✔
1101
show(io::IO, r::OneTo) = print(io, "Base.OneTo(", r.stop, ")")
80✔
1102
function show(io::IO, r::StepRangeLen)
11✔
1103
    if step(r) != 0
11✔
1104
        print(io, repr(first(r)), ':', repr(step(r)), ':', repr(last(r)))
7✔
1105
    else
1106
        # ugly temporary printing, to avoid 0:0:0 etc.
1107
        print(io, "StepRangeLen(", repr(first(r)), ", ", repr(step(r)), ", ", repr(length(r)), ")")
4✔
1108
    end
1109
end
1110

1111
function ==(r::T, s::T) where {T<:AbstractRange}
×
1112
    isempty(r) && return isempty(s)
×
1113
    _has_length_one(r) && return _has_length_one(s) & (first(r) == first(s))
×
1114
    (first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s))
×
1115
end
1116

1117
function ==(r::OrdinalRange, s::OrdinalRange)
240✔
1118
    isempty(r) && return isempty(s)
254✔
1119
    _has_length_one(r) && return _has_length_one(s) & (first(r) == first(s))
197✔
1120
    (first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s))
135✔
1121
end
1122

1123
==(r::AbstractUnitRange, s::AbstractUnitRange) =
17,790✔
1124
    (isempty(r) & isempty(s)) | ((first(r) == first(s)) & (last(r) == last(s)))
1125

1126
==(r::OneTo, s::OneTo) = last(r) == last(s)
10,820,388✔
1127

1128
==(r::T, s::T) where {T<:Union{StepRangeLen,LinRange}} =
157✔
1129
    (isempty(r) & isempty(s)) | ((first(r) == first(s)) & (length(r) == length(s)) & (last(r) == last(s)))
1130

1131
function ==(r::Union{StepRange{T},StepRangeLen{T,T}}, s::Union{StepRange{T},StepRangeLen{T,T}}) where {T}
137✔
1132
    isempty(r) && return isempty(s)
139✔
1133
    _has_length_one(r) && return _has_length_one(s) & (first(r) == first(s))
127✔
1134
    (first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s))
111✔
1135
end
1136

1137
_has_length_one(r::OrdinalRange) = first(r) == last(r)
383✔
1138
_has_length_one(r::AbstractRange) = isone(length(r))
19✔
1139

1140
function ==(r::AbstractRange, s::AbstractRange)
619✔
1141
    lr = length(r)
631✔
1142
    if lr != length(s)
631✔
1143
        return false
416✔
1144
    elseif iszero(lr)
203✔
1145
        return true
24✔
1146
    end
1147
    yr, ys = iterate(r), iterate(s)
358✔
1148
    while yr !== nothing
1,146✔
1149
        yr[1] == ys[1] || return false
1,001✔
1150
        yr, ys = iterate(r, yr[2]), iterate(s, ys[2])
1,772✔
1151
    end
967✔
1152
    return true
162✔
1153
end
1154

1155
intersect(r::OneTo, s::OneTo) = OneTo(min(r.stop,s.stop))
2,948✔
1156
union(r::OneTo, s::OneTo) = OneTo(max(r.stop,s.stop))
1✔
1157

1158
intersect(r::AbstractUnitRange{<:Integer}, s::AbstractUnitRange{<:Integer}) = max(first(r),first(s)):min(last(r),last(s))
27✔
1159

1160
intersect(i::Integer, r::AbstractUnitRange{<:Integer}) = range(max(i, first(r)), length=in(i, r))
185✔
1161

1162
intersect(r::AbstractUnitRange{<:Integer}, i::Integer) = intersect(i, r)
4✔
1163

1164
function intersect(r::AbstractUnitRange{<:Integer}, s::StepRange{<:Integer})
33✔
1165
    T = promote_type(eltype(r), eltype(s))
33✔
1166
    if isempty(s)
33✔
1167
        StepRange{T}(first(r), +step(s), first(r)-step(s))
8✔
1168
    else
1169
        sta, ste, sto = first_step_last_ascending(s)
41✔
1170
        lo = first(r)
25✔
1171
        hi = last(r)
25✔
1172
        i0 = max(sta, lo + mod(sta - lo, ste))
50✔
1173
        i1 = min(sto, hi - mod(hi - sta, ste))
42✔
1174
        StepRange{T}(i0, ste, i1)
25✔
1175
    end
1176
end
1177

1178
function first_step_last_ascending(r::StepRange)
65✔
1179
    if step(r) < zero(step(r))
65✔
1180
        last(r), -step(r), first(r)
12✔
1181
    else
1182
        first(r), +step(r), last(r)
53✔
1183
    end
1184
end
1185

1186
function intersect(r::StepRange{<:Integer}, s::AbstractUnitRange{<:Integer})
14✔
1187
    if step(r) < 0
14✔
1188
        reverse(intersect(s, reverse(r)))
5✔
1189
    else
1190
        intersect(s, r)
9✔
1191
    end
1192
end
1193

1194
function intersect(r::StepRange, s::StepRange)
20✔
1195
    T = promote_type(eltype(r), eltype(s))
20✔
1196
    S = promote_type(typeof(step(r)), typeof(step(s)))
20✔
1197
    if isempty(r) || isempty(s)
40✔
1198
        return StepRange{T,S}(first(r), step(r), first(r)-step(r))
×
1199
    end
1200

1201
    start1, step1, stop1 = first_step_last_ascending(r)
37✔
1202
    start2, step2, stop2 = first_step_last_ascending(s)
37✔
1203
    a = lcm(step1, step2)
20✔
1204

1205
    g, x, y = gcdx(step1, step2)
40✔
1206

1207
    if !iszero(rem(start1 - start2, g))
20✔
1208
        # Unaligned, no overlap possible.
1209
        if  step(r) < zero(step(r))
3✔
1210
            return StepRange{T,S}(stop1, -a, stop1+a)
×
1211
        else
1212
            return StepRange{T,S}(start1, a, start1-a)
3✔
1213
        end
1214
    end
1215

1216
    z = div(start1 - start2, g)
17✔
1217
    b = start1 - x * z * step1
17✔
1218
    # Possible points of the intersection of r and s are
1219
    # ..., b-2a, b-a, b, b+a, b+2a, ...
1220
    # Determine where in the sequence to start and stop.
1221
    m = max(start1 + mod(b - start1, a), start2 + mod(b - start2, a))
32✔
1222
    n = min(stop1 - mod(stop1 - b, a), stop2 - mod(stop2 - b, a))
32✔
1223
    step(r) < zero(step(r)) ? StepRange{T,S}(n, -a, m) : StepRange{T,S}(m, a, n)
17✔
1224
end
1225

1226
function intersect(r1::AbstractRange, r2::AbstractRange)
16✔
1227
    # To iterate over the shorter range
1228
    length(r1) > length(r2) && return intersect(r2, r1)
19✔
1229

1230
    r1 = unique(r1)
12✔
1231
    T = promote_eltype(r1, r2)
12✔
1232

1233
    return T[x for x in r1 if x ∈ r2]
12✔
1234
end
1235

1236
function intersect(r1::AbstractRange, r2::AbstractRange, r3::AbstractRange, r::AbstractRange...)
2✔
1237
    i = intersect(intersect(r1, r2), r3)
4✔
1238
    for t in r
2✔
1239
        i = intersect(i, t)
2✔
1240
    end
1✔
1241
    i
2✔
1242
end
1243

1244
# _findin (the index of intersection)
1245
function _findin(r::AbstractRange{<:Integer}, span::AbstractUnitRange{<:Integer})
12✔
1246
    fspan = first(span)
12✔
1247
    lspan = last(span)
12✔
1248
    fr = first(r)
12✔
1249
    lr = last(r)
12✔
1250
    sr = step(r)
12✔
1251
    if sr > 0
12✔
1252
        ifirst = fr >= fspan ? 1 : cld(fspan-fr, sr)+1
11✔
1253
        ilast = lr <= lspan ? length(r) : length(r) - cld(lr-lspan, sr)
12✔
1254
    elseif sr < 0
3✔
1255
        ifirst = fr <= lspan ? 1 : cld(lspan-fr, sr)+1
5✔
1256
        ilast = lr >= fspan ? length(r) : length(r) - cld(lr-fspan, sr)
3✔
1257
    else
1258
        ifirst = fr >= fspan ? 1 : length(r)+1
×
1259
        ilast = fr <= lspan ? length(r) : 0
×
1260
    end
1261
    r isa AbstractUnitRange ? (ifirst:ilast) : (ifirst:1:ilast)
12✔
1262
end
1263

1264
issubset(r::OneTo, s::OneTo) = r.stop <= s.stop
4✔
1265

1266
issubset(r::AbstractUnitRange{<:Integer}, s::AbstractUnitRange{<:Integer}) =
10✔
1267
    isempty(r) || (first(r) >= first(s) && last(r) <= last(s))
1268

1269
## linear operations on ranges ##
1270

1271
-(r::OrdinalRange) = range(-first(r), step=negate(step(r)), length=length(r))
152✔
1272
-(r::StepRangeLen{T,R,S,L}) where {T,R,S,L} =
39✔
1273
    StepRangeLen{T,R,S,L}(-r.ref, -r.step, r.len, r.offset)
1274
function -(r::LinRange)
2✔
1275
    start = -r.start
2✔
1276
    LinRange{typeof(start)}(start, -r.stop, length(r))
2✔
1277
end
1278

1279
# promote eltype if at least one container wouldn't change, otherwise join container types.
1280
el_same(::Type{T}, a::Type{<:AbstractArray{T,n}}, b::Type{<:AbstractArray{T,n}}) where {T,n}   = a # we assume a === b
7✔
1281
el_same(::Type{T}, a::Type{<:AbstractArray{T,n}}, b::Type{<:AbstractArray{S,n}}) where {T,S,n} = a
62✔
1282
el_same(::Type{T}, a::Type{<:AbstractArray{S,n}}, b::Type{<:AbstractArray{T,n}}) where {T,S,n} = b
41✔
1283
el_same(::Type, a, b) = promote_typejoin(a, b)
14✔
1284

1285
promote_rule(a::Type{UnitRange{T1}}, b::Type{UnitRange{T2}}) where {T1,T2} =
6✔
1286
    el_same(promote_type(T1, T2), a, b)
1287
UnitRange{T}(r::UnitRange{T}) where {T<:Real} = r
2✔
1288
UnitRange{T}(r::UnitRange) where {T<:Real} = UnitRange{T}(r.start, r.stop)
229✔
1289

1290
promote_rule(a::Type{OneTo{T1}}, b::Type{OneTo{T2}}) where {T1,T2} =
×
1291
    el_same(promote_type(T1, T2), a, b)
1292
OneTo{T}(r::OneTo{T}) where {T<:Integer} = r
×
1293
OneTo{T}(r::OneTo) where {T<:Integer} = OneTo{T}(r.stop)
4,955✔
1294

1295
promote_rule(a::Type{UnitRange{T1}}, ::Type{UR}) where {T1,UR<:AbstractUnitRange} =
4✔
1296
    promote_rule(a, UnitRange{eltype(UR)})
1297
UnitRange{T}(r::AbstractUnitRange) where {T<:Real} = UnitRange{T}(first(r), last(r))
588✔
1298
UnitRange(r::AbstractUnitRange) = UnitRange(first(r), last(r))
4,591✔
1299

1300
AbstractUnitRange{T}(r::AbstractUnitRange{T}) where {T} = r
×
1301
AbstractUnitRange{T}(r::UnitRange) where {T} = UnitRange{T}(r)
×
1302
AbstractUnitRange{T}(r::OneTo) where {T} = OneTo{T}(r)
4,763✔
1303

1304
OrdinalRange{T, S}(r::OrdinalRange) where {T, S} = StepRange{T, S}(r)
1✔
1305
OrdinalRange{T, T}(r::AbstractUnitRange) where {T} = AbstractUnitRange{T}(r)
4,448✔
1306

1307
function promote_rule(::Type{StepRange{T1a,T1b}}, ::Type{StepRange{T2a,T2b}}) where {T1a,T1b,T2a,T2b}
5✔
1308
    Tb = promote_type(T1b, T2b)
5✔
1309
    # el_same only operates on array element type, so just promote second type parameter
1310
    el_same(promote_type(T1a, T2a), StepRange{T1a,Tb}, StepRange{T2a,Tb})
5✔
1311
end
1312
StepRange{T1,T2}(r::StepRange{T1,T2}) where {T1,T2} = r
6✔
1313

1314
promote_rule(a::Type{StepRange{T1a,T1b}}, ::Type{UR}) where {T1a,T1b,UR<:AbstractUnitRange} =
3✔
1315
    promote_rule(a, StepRange{eltype(UR), eltype(UR)})
1316
StepRange{T1,T2}(r::AbstractRange) where {T1,T2} =
24✔
1317
    StepRange{T1,T2}(convert(T1, first(r)), convert(T2, step(r)), convert(T1, last(r)))
1318
StepRange(r::AbstractUnitRange{T}) where {T} =
1✔
1319
    StepRange{T,T}(first(r), step(r), last(r))
1320
(StepRange{T1,T2} where T1)(r::AbstractRange) where {T2} = StepRange{eltype(r),T2}(r)
2✔
1321

1322
function promote_rule(::Type{StepRangeLen{T1,R1,S1,L1}},::Type{StepRangeLen{T2,R2,S2,L2}}) where {T1,T2,R1,R2,S1,S2,L1,L2}
63✔
1323
    R, S, L = promote_type(R1, R2), promote_type(S1, S2), promote_type(L1, L2)
63✔
1324
    el_same(promote_type(T1, T2), StepRangeLen{T1,R,S,L}, StepRangeLen{T2,R,S,L})
63✔
1325
end
1326
StepRangeLen{T,R,S,L}(r::StepRangeLen{T,R,S,L}) where {T,R,S,L} = r
×
1327
StepRangeLen{T,R,S,L}(r::StepRangeLen) where {T,R,S,L} =
14✔
1328
    StepRangeLen{T,R,S,L}(convert(R, r.ref), convert(S, r.step), convert(L, r.len), convert(L, r.offset))
1329
StepRangeLen{T}(r::StepRangeLen) where {T} =
×
1330
    StepRangeLen(convert(T, r.ref), convert(T, r.step), r.len, r.offset)
1331

1332
promote_rule(a::Type{StepRangeLen{T,R,S,L}}, ::Type{OR}) where {T,R,S,L,OR<:AbstractRange} =
37✔
1333
    promote_rule(a, StepRangeLen{eltype(OR), eltype(OR), eltype(OR), Int})
1334
StepRangeLen{T,R,S,L}(r::AbstractRange) where {T,R,S,L} =
125✔
1335
    StepRangeLen{T,R,S,L}(R(first(r)), S(step(r)), length(r))
1336
StepRangeLen{T}(r::AbstractRange) where {T} =
4✔
1337
    StepRangeLen(T(first(r)), T(step(r)), length(r))
1338
StepRangeLen(r::AbstractRange) = StepRangeLen{eltype(r)}(r)
2✔
1339

1340
function promote_rule(a::Type{LinRange{T1,L1}}, b::Type{LinRange{T2,L2}}) where {T1,T2,L1,L2}
×
1341
    L = promote_type(L1, L2)
×
1342
    el_same(promote_type(T1, T2), LinRange{T1,L}, LinRange{T2,L})
×
1343
end
1344
LinRange{T,L}(r::LinRange{T,L}) where {T,L} = r
×
1345
LinRange{T,L}(r::AbstractRange) where {T,L} = LinRange{T,L}(first(r), last(r), length(r))
×
1346
LinRange{T}(r::AbstractRange) where {T} = LinRange{T,typeof(length(r))}(first(r), last(r), length(r))
11✔
1347
LinRange(r::AbstractRange{T}) where {T} = LinRange{T}(r)
4✔
1348

1349
promote_rule(a::Type{LinRange{T,L}}, ::Type{OR}) where {T,L,OR<:OrdinalRange} =
×
1350
    promote_rule(a, LinRange{eltype(OR),L})
1351

1352
promote_rule(::Type{LinRange{A,L}}, b::Type{StepRangeLen{T2,R2,S2,L2}}) where {A,L,T2,R2,S2,L2} =
14✔
1353
    promote_rule(StepRangeLen{A,A,A,L}, b)
1354

1355
## concatenation ##
1356

1357
function vcat(rs::AbstractRange{T}...) where T
11,074,673✔
1358
    n::Int = 0
11,074,673✔
1359
    for ra in rs
53,700,250✔
1360
        n += length(ra)
53,700,561✔
1361
    end
11,070,378✔
1362
    a = Vector{T}(undef, n)
53,700,250✔
1363
    i = 1
11,069,803✔
1364
    for ra in rs, x in ra
65,522,428✔
1365
        @inbounds a[i] = x
79,757,347✔
1366
        i += 1
79,757,347✔
1367
    end
147,686,644✔
1368
    return a
53,700,250✔
1369
end
1370

1371
Array{T,1}(r::AbstractRange{T}) where {T} = vcat(r)
8,362✔
1372
collect(r::AbstractRange) = vcat(r)
52,400,260✔
1373

1374
_reverse(r::OrdinalRange, ::Colon) = (:)(last(r), negate(step(r)), first(r))
43,877,338✔
1375
function _reverse(r::StepRangeLen, ::Colon)
55✔
1376
    # If `r` is empty, `length(r) - r.offset + 1 will be nonpositive hence
1377
    # invalid. As `reverse(r)` is also empty, any offset would work so we keep
1378
    # `r.offset`
1379
    offset = isempty(r) ? r.offset : length(r)-r.offset+1
106✔
1380
    return typeof(r)(r.ref, negate(r.step), length(r), offset)
55✔
1381
end
1382
_reverse(r::LinRange{T}, ::Colon) where {T} = typeof(r)(r.stop, r.start, length(r))
2✔
1383

1384
## sorting ##
1385

1386
issorted(r::AbstractUnitRange) = true
3,349✔
1387
issorted(r::AbstractRange) = length(r) <= 1 || step(r) >= zero(step(r))
202✔
1388

1389
sort(r::AbstractUnitRange) = r
1✔
1390
sort!(r::AbstractUnitRange) = r
1✔
1391

1392
sort(r::AbstractRange) = issorted(r) ? r : reverse(r)
×
1393

1394
sortperm(r::AbstractUnitRange) = 1:length(r)
×
1395
sortperm(r::AbstractRange) = issorted(r) ? (1:1:length(r)) : (length(r):-1:1)
50✔
1396

1397
function sum(r::AbstractRange{<:Real})
43✔
1398
    l = length(r)
43✔
1399
    # note that a little care is required to avoid overflow in l*(l-1)/2
1400
    return l * first(r) + (iseven(l) ? (step(r) * (l-1)) * (l>>1)
43✔
1401
                                     : (step(r) * l) * ((l-1)>>1))
1402
end
1403

1404
function _in_range(x, r::AbstractRange)
845✔
1405
    isempty(r) && return false
845✔
1406
    f, l = first(r), last(r)
844✔
1407
    # check for NaN, Inf, and large x that may overflow in the next calculation
1408
    f <= x <= l || l <= x <= f || return false
1,240✔
1409
    iszero(step(r)) && return true
764✔
1410
    n = round(Integer, (x - f) / step(r)) + 1
763✔
1411
    n >= 1 && n <= length(r) && r[n] == x
763✔
1412
end
1413
in(x::Real, r::AbstractRange{<:Real}) = _in_range(x, r)
840✔
1414
# This method needs to be defined separately since -(::T, ::T) can be implemented
1415
# even if -(::T, ::Real) is not
1416
in(x::T, r::AbstractRange{T}) where {T} = _in_range(x, r)
5✔
1417

1418
in(x::Integer, r::AbstractUnitRange{<:Integer}) = (first(r) <= x) & (x <= last(r))
225,489,449✔
1419

1420
in(x::Real, r::AbstractRange{T}) where {T<:Integer} =
3,101✔
1421
    isinteger(x) && !isempty(r) &&
1422
    (iszero(step(r)) ? x == first(r) : (x >= minimum(r) && x <= maximum(r) &&
1423
        (mod(convert(T,x),step(r))-mod(first(r),step(r)) == 0)))
1424
in(x::AbstractChar, r::AbstractRange{<:AbstractChar}) =
80✔
1425
    !isempty(r) &&
1426
    (iszero(step(r)) ? x == first(r) : (x >= minimum(r) && x <= maximum(r) &&
1427
        (mod(Int(x) - Int(first(r)), step(r)) == 0)))
1428

1429
# Addition/subtraction of ranges
1430

1431
function _define_range_op(@nospecialize f)
1432
    @eval begin
1433
        function $f(r1::OrdinalRange, r2::OrdinalRange)
199✔
1434
            r1l = length(r1)
199✔
1435
            (r1l == length(r2) ||
201✔
1436
             throw(DimensionMismatch("argument dimensions must match: length of r1 is $r1l, length of r2 is $(length(r2))")))
1437
            StepRangeLen($f(first(r1), first(r2)), $f(step(r1), step(r2)), r1l)
197✔
1438
        end
1439

1440
        function $f(r1::LinRange{T}, r2::LinRange{T}) where T
1441
            len = r1.len
1442
            (len == r2.len ||
1443
             throw(DimensionMismatch("argument dimensions must match: length of r1 is $len, length of r2 is $(r2.len)")))
1444
            LinRange{T}(convert(T, $f(first(r1), first(r2))),
1445
                        convert(T, $f(last(r1), last(r2))), len)
1446
        end
1447

1448
        $f(r1::Union{StepRangeLen, OrdinalRange, LinRange},
1449
           r2::Union{StepRangeLen, OrdinalRange, LinRange}) =
25✔
1450
               $f(promote(r1, r2)...)
1451
    end
1452
end
1453
_define_range_op(:+)
1454
_define_range_op(:-)
1455

1456
function +(r1::StepRangeLen{T,S}, r2::StepRangeLen{T,S}) where {T,S}
8✔
1457
    len = length(r1)
8✔
1458
    (len == length(r2) ||
8✔
1459
     throw(DimensionMismatch("argument dimensions must match: length of r1 is $len, length of r2 is $(length(r2))")))
1460
    StepRangeLen(first(r1)+first(r2), step(r1)+step(r2), len)
8✔
1461
end
1462

1463
-(r1::StepRangeLen, r2::StepRangeLen) = +(r1, -r2)
17✔
1464

1465
# Modular arithmetic on ranges
1466

1467
"""
1468
    mod(x::Integer, r::AbstractUnitRange)
1469

1470
Find `y` in the range `r` such that ``x ≡ y (mod n)``, where `n = length(r)`,
1471
i.e. `y = mod(x - first(r), n) + first(r)`.
1472

1473
See also [`mod1`](@ref).
1474

1475
# Examples
1476
```jldoctest
1477
julia> mod(0, Base.OneTo(3))  # mod1(0, 3)
1478
3
1479

1480
julia> mod(3, 0:2)  # mod(3, 3)
1481
0
1482
```
1483

1484
!!! compat "Julia 1.3"
1485
     This method requires at least Julia 1.3.
1486
"""
1487
mod(i::Integer, r::OneTo) = mod1(i, last(r))
21✔
1488
mod(i::Integer, r::AbstractUnitRange{<:Integer}) = mod(i-first(r), length(r)) + first(r)
66✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc