Skip to content

Commit 879e3e6

Browse files
committed
Fix length for StepRange
1 parent 8ea98a7 commit 879e3e6

File tree

3 files changed

+39
-2
lines changed

3 files changed

+39
-2
lines changed

src/FixedPointNumbers.jl

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

11-
using Base.Checked: checked_add, checked_sub
11+
using Base.Checked: checked_add, checked_sub, checked_div
1212

1313
using Base: @pure
1414

@@ -151,6 +151,26 @@ for (m, f) in ((:(:Nearest), :round),
151151
end
152152
end
153153

154+
function Base.unsafe_length(r::StepRange{X,X}) where {X <: FixedPoint{<:ShorterThanInt}}
155+
start, step, stop = reinterpret(r.start), reinterpret(r.step), reinterpret(r.stop)
156+
return div(Int(stop) - Int(start) + Int(step), Int(step))
157+
end
158+
function Base.unsafe_length(r::StepRange{X,X}) where {X <: FixedPoint}
159+
start, step, stop = reinterpret(r.start), reinterpret(r.step), reinterpret(r.stop)
160+
return div((stop - start) + step, step)
161+
end
162+
function Base.unsafe_length(r::StepRange{<:FixedPoint})
163+
start, step, stop = float(r.start), r.step, float(r.stop)
164+
return div((stop - start) + step, step)
165+
end
166+
Base.length(r::StepRange{X,X}) where {X <: FixedPoint{<:ShorterThanInt}} =
167+
Base.unsafe_length(r)
168+
function Base.length(r::StepRange{X,X}) where {X <: FixedPoint}
169+
start, step, stop = reinterpret(r.start), reinterpret(r.step), reinterpret(r.stop)
170+
return checked_div(checked_add(checked_sub(stop, start), step), step)
171+
end
172+
Base.length(r::StepRange{<:FixedPoint}) = Base.unsafe_length(r)
173+
154174
# Printing. These are used to generate type-symbols, so we need them
155175
# before we include any files.
156176
function showtype(io::IO, ::Type{X}) where {X <: FixedPoint}

test/fixed.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,20 @@ end
194194
@test_throws OverflowError length(typemin(QInt1):typemax(QInt1))
195195
end
196196

197+
@testset "step range" begin
198+
r = typemin(Q0f7):eps(Q0f7):typemax(Q0f7)
199+
counter = 0
200+
for x in r
201+
counter += 1
202+
end
203+
@test counter == 256
204+
@test length(r) == 256
205+
QInt1 = Fixed{Int,1}
206+
@test length(QInt1(0):eps(QInt1):typemax(QInt1)-eps(QInt1)) == typemax(Int)
207+
@test Base.unsafe_length(typemin(QInt1):eps(QInt1):typemax(QInt1)-eps(QInt1)) == -1
208+
@test_throws OverflowError length(QInt1(-1):eps(QInt1):typemax(QInt1)-eps(QInt1))
209+
end
210+
197211
@testset "reductions" begin
198212
a = Q0f7[0.75, 0.5]
199213
acmp = Float64(a[1]) + Float64(a[2])

test/normed.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,11 @@ end
323323
end
324324
@test counter == 256
325325
@test length(N0f8(0):eps(N0f8):N0f8(1)) == 256
326-
r = reinterpret(N0f8, 0x01):reinterpret(N0f8, 0x01):reinterpret(N0f8, convert(UInt8, 48))
326+
r = reinterpret(N0f8, 0x01):reinterpret(N0f8, 0x01):reinterpret(N0f8, UInt8(48))
327327
@test length(r) == 48
328+
NInt1 = Normed{UInt,1}
329+
@test length(NInt1(0):NInt1(1):typemax(NInt1)-oneunit(NInt1)) == typemax(UInt)
330+
@test_throws OverflowError length(NInt1(0):NInt1(1):typemax(NInt1))
328331
end
329332

330333
@testset "Promotion within Normed" begin

0 commit comments

Comments
 (0)