Skip to content

Commit e603b25

Browse files
mbaumanLilithHafner
authored andcommitted
Fix reverse of ranges of unsigned integers (JuliaLang#29842)
Fixes JuliaLang#29576 Co-authored-by: Jameson Nash <[email protected]> Co-authored-by: Lilith Orion Hafner <[email protected]>
1 parent 19a68b1 commit e603b25

File tree

5 files changed

+27
-14
lines changed

5 files changed

+27
-14
lines changed

base/broadcast.jl

+7-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module Broadcast
99

1010
using .Base.Cartesian
1111
using .Base: Indices, OneTo, tail, to_shape, isoperator, promote_typejoin, promote_typejoin_union, @pure,
12-
_msk_end, unsafe_bitgetindex, bitcache_chunks, bitcache_size, dumpbitcache, unalias
12+
_msk_end, unsafe_bitgetindex, bitcache_chunks, bitcache_size, dumpbitcache, unalias, negate
1313
import .Base: copy, copyto!, axes
1414
export broadcast, broadcast!, BroadcastStyle, broadcast_axes, broadcastable, dotview, @__dot__, BroadcastFunction
1515

@@ -1079,9 +1079,9 @@ end
10791079
# DefaultArrayStyle and \ are not available at the time of range.jl
10801080
broadcasted(::DefaultArrayStyle{1}, ::typeof(+), r::AbstractRange) = r
10811081

1082-
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::AbstractRange) = range(-first(r), step=-step(r), length=length(r))
1083-
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::OrdinalRange) = range(-first(r), -last(r), step=-step(r))
1084-
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::StepRangeLen) = StepRangeLen(-r.ref, -r.step, length(r), r.offset)
1082+
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::AbstractRange) = range(-first(r), step=negate(step(r)), length=length(r))
1083+
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::OrdinalRange) = range(-first(r), -last(r), step=negate(step(r)))
1084+
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::StepRangeLen) = StepRangeLen(-r.ref, negate(r.step), length(r), r.offset)
10851085
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::LinRange) = LinRange(-r.start, -r.stop, length(r))
10861086

10871087
# For #18336 we need to prevent promotion of the step type:
@@ -1102,15 +1102,15 @@ broadcasted(::DefaultArrayStyle{1}, ::typeof(+), x::Number, r::LinRange) = LinRa
11021102
broadcasted(::DefaultArrayStyle{1}, ::typeof(+), r1::AbstractRange, r2::AbstractRange) = r1 + r2
11031103

11041104
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::AbstractRange, x::Number) = range(first(r) - x, step=step(r), length=length(r))
1105-
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), x::Number, r::AbstractRange) = range(x - first(r), step=-step(r), length=length(r))
1105+
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), x::Number, r::AbstractRange) = range(x - first(r), step=negate(step(r)), length=length(r))
11061106
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::OrdinalRange, x::Integer) = range(first(r) - x, last(r) - x, step=step(r))
1107-
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), x::Integer, r::OrdinalRange) = range(x - first(r), x - last(r), step=-step(r))
1107+
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), x::Integer, r::OrdinalRange) = range(x - first(r), x - last(r), step=negate(step(r)))
11081108
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::AbstractUnitRange, x::Integer) = range(first(r) - x, last(r) - x)
11091109
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::AbstractUnitRange, x::Real) = range(first(r) - x, length=length(r))
11101110
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::StepRangeLen{T}, x::Number) where T =
11111111
StepRangeLen{typeof(T(r.ref)-x)}(r.ref - x, r.step, length(r), r.offset)
11121112
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), x::Number, r::StepRangeLen{T}) where T =
1113-
StepRangeLen{typeof(x-T(r.ref))}(x - r.ref, -r.step, length(r), r.offset)
1113+
StepRangeLen{typeof(x-T(r.ref))}(x - r.ref, negate(r.step), length(r), r.offset)
11141114
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::LinRange, x::Number) = LinRange(r.start - x, r.stop - x, length(r))
11151115
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), x::Number, r::LinRange) = LinRange(x - r.start, x - r.stop, length(r))
11161116
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r1::AbstractRange, r2::AbstractRange) = r1 - r2

base/int.jl

+4
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ signed(::Type{T}) where {T<:Signed} = T
8787
(+)(x::T, y::T) where {T<:BitInteger} = add_int(x, y)
8888
(*)(x::T, y::T) where {T<:BitInteger} = mul_int(x, y)
8989

90+
negate(x) = -x
91+
negate(x::Unsigned) = -convert(Signed, x)
92+
#widenegate(x) = -convert(widen(signed(typeof(x))), x)
93+
9094
inv(x::Integer) = float(one(x)) / float(x)
9195
(/)(x::T, y::T) where {T<:Integer} = float(x) / float(y)
9296
# skip promotion for system integer types

base/range.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -1246,7 +1246,7 @@ issubset(r::AbstractUnitRange{<:Integer}, s::AbstractUnitRange{<:Integer}) =
12461246

12471247
## linear operations on ranges ##
12481248

1249-
-(r::OrdinalRange) = range(-first(r), step=-step(r), length=length(r))
1249+
-(r::OrdinalRange) = range(-first(r), step=negate(step(r)), length=length(r))
12501250
-(r::StepRangeLen{T,R,S,L}) where {T,R,S,L} =
12511251
StepRangeLen{T,R,S,L}(-r.ref, -r.step, r.len, r.offset)
12521252
function -(r::LinRange)
@@ -1352,13 +1352,13 @@ end
13521352
Array{T,1}(r::AbstractRange{T}) where {T} = vcat(r)
13531353
collect(r::AbstractRange) = vcat(r)
13541354

1355-
_reverse(r::OrdinalRange, ::Colon) = (:)(last(r), -step(r), first(r))
1355+
_reverse(r::OrdinalRange, ::Colon) = (:)(last(r), negate(step(r)), first(r))
13561356
function _reverse(r::StepRangeLen, ::Colon)
13571357
# If `r` is empty, `length(r) - r.offset + 1 will be nonpositive hence
13581358
# invalid. As `reverse(r)` is also empty, any offset would work so we keep
13591359
# `r.offset`
13601360
offset = isempty(r) ? r.offset : length(r)-r.offset+1
1361-
return typeof(r)(r.ref, -r.step, length(r), offset)
1361+
return typeof(r)(r.ref, negate(r.step), length(r), offset)
13621362
end
13631363
_reverse(r::LinRange{T}, ::Colon) where {T} = typeof(r)(r.stop, r.start, length(r))
13641364

test/ranges.jl

+11-3
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,14 @@ end
382382
@test reverse(reverse(typemin(Int):typemax(Int))) == typemin(Int):typemax(Int)
383383
@test reverse(reverse(typemin(Int):2:typemax(Int))) == typemin(Int):2:typemax(Int)
384384
end
385+
@testset "reverse `[Step|Unit]Range{$T}`" for T in (Int8, UInt8, Int, UInt, Int128, UInt128)
386+
@test reverse(T(1):T(10)) == T(10):-1:T(1)
387+
@test reverse(typemin(T):typemax(T)) == typemax(T):-1:typemin(T)
388+
@test reverse(typemin(T):2:typemax(T)) == typemax(T)-T(1):-2:typemin(T)
389+
@test reverse(reverse(T(1):T(10))) == T(1):T(10)
390+
@test reverse(reverse(typemin(T):typemax(T))) == typemin(T):typemax(T)
391+
@test reverse(reverse(typemin(T):2:typemax(T))) == typemin(T):2:typemax(T)
392+
end
385393
@testset "intersect" begin
386394
@test intersect(1:5, 2:3) === 2:3
387395
@test intersect(-3:5, 2:8) === 2:5
@@ -717,9 +725,9 @@ end
717725
@test broadcast(-, T(1):2:6, 1) === T(0):2:4
718726
@test broadcast(-, T(1):2:6, 0.3) === range(T(1)-0.3, step=2, length=T(3)) == T(1)-0.3:2:5-0.3
719727
is_unsigned = T <: Unsigned
720-
is_unsigned && @test length(broadcast(-, T(1):3, 2)) === length(T(1)-2:T(3)-2)
721-
@test broadcast(-, T(1):3) == -T(1):-T(1):-T(3)
722-
@test broadcast(-, 2, T(1):3) == T(1):-T(1):-T(1)
728+
@test length(broadcast(-, T(1):3, 2)) === length(T(1)-2:T(3)-2) === (is_unsigned ? T(0) : T(3))
729+
@test broadcast(-, T(1):3) == -T(1):-1:-T(3)
730+
@test broadcast(-, 2, T(1):3) == T(1):-1:-T(1)
723731
end
724732
@testset "operations between ranges and arrays" for T in (Int, UInt, Int128)
725733
@test all(([T(1):5;] + (T(5):-1:1)) .=== T(6))

test/sorting.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ end
5656
@test issorted([1,2,3])
5757
@test reverse([2,3,1]) == [1,3,2]
5858
@test sum(randperm(6)) == 21
59+
@test length(reverse(0x1:0x2)) == 2
60+
@test issorted(sort(rand(UInt64(1):UInt64(2), 7); rev=true); rev=true) # issue #43034
5961
end
6062

6163
@testset "partialsort" begin
@@ -220,7 +222,6 @@ end
220222
end
221223
end
222224

223-
@test_broken length(reverse(0x1:0x2)) == 2
224225
@testset "issue #34408" begin
225226
r = 1f8-10:1f8
226227
# collect(r) = Float32[9.999999e7, 9.999999e7, 9.999999e7, 9.999999e7, 1.0e8, 1.0e8, 1.0e8, 1.0e8, 1.0e8]

0 commit comments

Comments
 (0)