Skip to content

Commit 8ea98a7

Browse files
committed
Fix UnitRange construction and length(r)
1 parent 402e637 commit 8ea98a7

File tree

6 files changed

+60
-4
lines changed

6 files changed

+60
-4
lines changed

src/FixedPointNumbers.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import Base: ==, <, <=, -, +, *, /, ~, isapprox,
88
div, fld, rem, mod, mod1, fld1, min, max, minmax,
99
rand
1010

11+
using Base.Checked: checked_add, checked_sub
12+
1113
using Base: @pure
1214

1315
"""

src/fixed.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,20 @@ function round(::Type{Ti}, x::Fixed{T,f}) where {Ti <: Integer, T, f}
161161
convert(Ti, z - Ti(y & m == rawone(x)))
162162
end
163163

164+
# Range construction
165+
Base.unitrange_last(start::F, stop::F) where {F<:Fixed} =
166+
stop >= start ? convert(F, start+floor(stop-start)) : convert(F, start+F(-1))
167+
168+
# Range lengths
169+
Base.unsafe_length(r::AbstractUnitRange{F}) where {F <: Fixed{<:Union{SShorterThanInt,Int},f}} where {f} =
170+
Int(reinterpret(last(r)) >> f - reinterpret(first(r)) >> f) + 1
171+
Base.unsafe_length(r::AbstractUnitRange{F}) where {F <: Fixed{T,f}} where {T<:Signed,f} =
172+
T(reinterpret(last(r)) >> f - reinterpret(first(r)) >> f) + oneunit(T)
173+
Base.length(r::AbstractUnitRange{F}) where {F <: Fixed{<:SShorterThanInt,f}} where {f} =
174+
Base.unsafe_length(r)
175+
Base.length(r::AbstractUnitRange{F}) where {F <: Fixed{T,f}} where {T<:Signed,f} =
176+
checked_add(checked_sub(T(reinterpret(last(r)) >> f), T(reinterpret(first(r)) >> f)), oneunit(T))
177+
164178
promote_rule(ft::Type{Fixed{T,f}}, ::Type{TI}) where {T,f,TI <: Integer} = Fixed{T,f}
165179
promote_rule(::Type{Fixed{T,f}}, ::Type{TF}) where {T,f,TF <: AbstractFloat} = TF
166180
promote_rule(::Type{Fixed{T,f}}, ::Type{Rational{TR}}) where {T,f,TR} = Rational{TR}

src/normed.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,16 @@ function decompose(x::Normed)
287287
div(reinterpret(x),g), 0, div(rawone(x),g)
288288
end
289289

290+
# Range lengths
291+
Base.unsafe_length(r::AbstractUnitRange{N}) where {N <: Normed{<:UShorterThanInt}} =
292+
Int(last(r)) - Int(first(r)) + 1
293+
Base.unsafe_length(r::AbstractUnitRange{N}) where {N <: Normed{T}} where {T<:Unsigned} =
294+
T(last(r)) - T(first(r)) + oneunit(T)
295+
Base.length(r::AbstractUnitRange{N}) where {N <: Normed{<:ShorterThanInt}} =
296+
Base.unsafe_length(r)
297+
Base.length(r::AbstractUnitRange{N}) where {N <: Normed{T}} where {T<:Integer} =
298+
checked_add(checked_sub(T(last(r)), T(first(r))), oneunit(T))
299+
290300
# Promotions
291301
promote_rule(::Type{T}, ::Type{Tf}) where {T <: Normed,Tf <: AbstractFloat} = promote_type(floattype(T), Tf)
292302
promote_rule(::Type{T}, ::Type{R}) where {T <: Normed,R <: Rational} = R

src/utilities.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ widen1(x::Integer) = x % widen1(typeof(x))
1616
const ShortInts = Union{Int8, UInt8, Int16, UInt16}
1717
const LongInts = Union{Int64, UInt64, Int128, UInt128, BigInt}
1818

19+
const ShorterThanInt = Int === Int32 ? ShortInts : Union{ShortInts, Int32, UInt32}
20+
const NotBiggerThanInt = Union{ShorterThanInt, Int, UInt}
21+
const SShorterThanInt = typeintersect(ShorterThanInt, Signed)
22+
const UShorterThanInt = typeintersect(ShorterThanInt, Unsigned)
23+
1924
macro f32(x::Float64) # just for hexadecimal floating-point literals
2025
:(Float32($x))
2126
end

test/fixed.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,17 @@ end
183183
end
184184
end
185185

186+
@testset "unit range" begin
187+
@test length(Q1f6(-1):Q1f6(0)) == 2
188+
@test collect(Q1f6(-1):Q1f6(0)) == Q1f6[-1, 0]
189+
@test length(Q6f1(-64):Q6f1(63)) == 128
190+
QIntW = Fixed{Int,bitwidth(Int)-1}
191+
@test length(QIntW(-1):QIntW(0)) == 2
192+
QInt1 = Fixed{Int,1}
193+
@test length(typemin(QInt1):typemax(QInt1)-oneunit(QInt1)) == typemax(Int)
194+
@test_throws OverflowError length(typemin(QInt1):typemax(QInt1))
195+
end
196+
186197
@testset "reductions" begin
187198
a = Q0f7[0.75, 0.5]
188199
acmp = Float64(a[1]) + Float64(a[2])

test/normed.jl

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,17 +300,31 @@ end
300300
@test bswap(N0f8(0.5)) === N0f8(0.5)
301301
@test bswap(N0f16(0.5)) === reinterpret(N0f16, 0x0080)
302302
@test minmax(N0f8(0.8), N0f8(0.2)) === (N0f8(0.2), N0f8(0.8))
303+
end
303304

304-
r = reinterpret(N0f8, 0x01):reinterpret(N0f8, 0x01):reinterpret(N0f8, convert(UInt8, 48))
305-
@test length(r) == 48
306-
end
305+
@testset "unit range" begin
306+
@test length(N0f8(0):N0f8(1)) == 2
307+
@test collect(N0f8(0):N0f8(1)) == N0f8[0, 1]
308+
@test length(N7f1(0):N7f1(255)) == 256
309+
NIntW = Normed{UInt,bitwidth(UInt)}
310+
@test length(NIntW(0):NIntW(1)) == 2
311+
NInt1 = Normed{UInt,1}
312+
@test length(NInt1(0):typemax(NInt1)-oneunit(NInt1)) == typemax(UInt)
313+
@test_throws OverflowError length(NInt1(0):typemax(NInt1))
314+
@test Base.unsafe_length(NInt1(0):typemax(NInt1)) == 0 # overflow
315+
N64f64 = Normed{UInt128,64}
316+
@test_broken length(N64f64(0):typemax(N64f64)) == UInt128(typemax(UInt64)) + 1
317+
end
307318

308-
@testset "step range" begin
319+
@testset "step range" begin
309320
counter = 0
310321
for x in N0f8(0):eps(N0f8):N0f8(1)
311322
counter += 1
312323
end
313324
@test counter == 256
325+
@test length(N0f8(0):eps(N0f8):N0f8(1)) == 256
326+
r = reinterpret(N0f8, 0x01):reinterpret(N0f8, 0x01):reinterpret(N0f8, convert(UInt8, 48))
327+
@test length(r) == 48
314328
end
315329

316330
@testset "Promotion within Normed" begin

0 commit comments

Comments
 (0)