Skip to content

Commit 68afe07

Browse files
mbaumanvtjnash
andcommitted
Fix reverse of ranges of unsigned integers
Fixes #29576 Co-authored-by: Jameson Nash <[email protected]>
1 parent c25b704 commit 68afe07

File tree

4 files changed

+25
-13
lines changed

4 files changed

+25
-13
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
@@ -1234,7 +1234,7 @@ issubset(r::AbstractUnitRange{<:Integer}, s::AbstractUnitRange{<:Integer}) =
12341234

12351235
## linear operations on ranges ##
12361236

1237-
-(r::OrdinalRange) = range(-first(r), step=-step(r), length=length(r))
1237+
-(r::OrdinalRange) = range(-first(r), step=negate(step(r)), length=length(r))
12381238
-(r::StepRangeLen{T,R,S,L}) where {T,R,S,L} =
12391239
StepRangeLen{T,R,S,L}(-r.ref, -r.step, r.len, r.offset)
12401240
function -(r::LinRange)
@@ -1340,13 +1340,13 @@ end
13401340
Array{T,1}(r::AbstractRange{T}) where {T} = vcat(r)
13411341
collect(r::AbstractRange) = vcat(r)
13421342

1343-
_reverse(r::OrdinalRange, ::Colon) = (:)(last(r), -step(r), first(r))
1343+
_reverse(r::OrdinalRange, ::Colon) = (:)(last(r), negate(step(r)), first(r))
13441344
function _reverse(r::StepRangeLen, ::Colon)
13451345
# If `r` is empty, `length(r) - r.offset + 1 will be nonpositive hence
13461346
# invalid. As `reverse(r)` is also empty, any offset would work so we keep
13471347
# `r.offset`
13481348
offset = isempty(r) ? r.offset : length(r)-r.offset+1
1349-
return typeof(r)(r.ref, -r.step, length(r), offset)
1349+
return typeof(r)(r.ref, negate(r.step), length(r), offset)
13501350
end
13511351
_reverse(r::LinRange{T}, ::Colon) where {T} = typeof(r)(r.stop, r.start, length(r))
13521352

test/ranges.jl

+11-3
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,14 @@ end
367367
@test reverse(reverse(typemin(Int):typemax(Int))) == typemin(Int):typemax(Int)
368368
@test reverse(reverse(typemin(Int):2:typemax(Int))) == typemin(Int):2:typemax(Int)
369369
end
370+
@testset "reverse `[Step|Unit]Range{$T}`" for T in (Int8, UInt8, Int, UInt, Int128, UInt128)
371+
@test reverse(T(1):T(10)) == T(10):-1:T(1)
372+
@test reverse(typemin(T):typemax(T)) == typemax(T):-1:typemin(T)
373+
@test reverse(typemin(T):2:typemax(T)) == typemax(T)-T(1):-2:typemin(T)
374+
@test reverse(reverse(T(1):T(10))) == T(1):T(10)
375+
@test reverse(reverse(typemin(T):typemax(T))) == typemin(T):typemax(T)
376+
@test reverse(reverse(typemin(T):2:typemax(T))) == typemin(T):2:typemax(T)
377+
end
370378
@testset "intersect" begin
371379
@test intersect(1:5, 2:3) == 2:3
372380
@test intersect(-3:5, 2:8) == 2:5
@@ -699,9 +707,9 @@ end
699707
@test broadcast(-, T(1):2:6, 1) === T(0):2:4
700708
@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
701709
is_unsigned = T <: Unsigned
702-
is_unsigned && @test length(broadcast(-, T(1):3, 2)) === length(T(1)-2:T(3)-2)
703-
@test broadcast(-, T(1):3) == -T(1):-T(1):-T(3)
704-
@test broadcast(-, 2, T(1):3) == T(1):-T(1):-T(1)
710+
@test length(broadcast(-, T(1):3, 2)) === length(T(1)-2:T(3)-2) === (is_unsigned ? T(0) : T(3))
711+
@test broadcast(-, T(1):3) == -T(1):-1:-T(3)
712+
@test broadcast(-, 2, T(1):3) == T(1):-1:-T(1)
705713
end
706714
@testset "operations between ranges and arrays" for T in (Int, UInt, Int128)
707715
@test all(([T(1):5;] + (T(5):-1:1)) .=== T(6))

0 commit comments

Comments
 (0)