Skip to content

Commit

Permalink
fix #5025, ordering used by nextfloat/prevfloat
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Dec 4, 2013
1 parent 893033c commit 72400ea
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 10 deletions.
24 changes: 18 additions & 6 deletions base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,24 @@ const NaN32 = box(Float32,unbox(Uint32,0x7fc00000))
const Inf = box(Float64,unbox(Uint64,0x7ff0000000000000))
const NaN = box(Float64,unbox(Uint64,0x7ff8000000000000))

function float_lex_order(f::Integer, delta::Integer)
# convert from signed magnitude to 2's complement and back
if f < 0
f = oftype(f, -(f & typemax(f)))
end
f = oftype(f, f + delta)
f < 0 ? oftype(f, -(f & typemax(f))) : f
end

nextfloat(x::Float16, i::Integer) =
reinterpret(Float16,float_lex_order(reinterpret(Int16,x), i))
nextfloat(x::Float32, i::Integer) =
reinterpret(Float32,float_lex_order(reinterpret(Int32,x), i))
nextfloat(x::Float64, i::Integer) =
reinterpret(Float64,float_lex_order(reinterpret(Int64,x), i))
nextfloat(x::FloatingPoint) = nextfloat(x,1)
prevfloat(x::FloatingPoint) = nextfloat(x,-1)

@eval begin
inf(::Type{Float16}) = $Inf16
nan(::Type{Float16}) = $NaN16
Expand Down Expand Up @@ -249,12 +267,6 @@ const NaN = box(Float64,unbox(Uint64,0x7ff8000000000000))
realmin() = realmin(Float64)
realmax() = realmax(Float64)

nextfloat(x::Float16, i::Integer) = box(Float16,add_int(reinterpret(Int16,x),unbox(Int16,int16(i))))
nextfloat(x::Float32, i::Integer) = box(Float32,add_int(unbox(Float32,x),unbox(Int32,int32(i))))
nextfloat(x::Float64, i::Integer) = box(Float64,add_int(unbox(Float64,x),unbox(Int64,int64(i))))
nextfloat(x::FloatingPoint) = nextfloat(x,1)
prevfloat(x::FloatingPoint) = nextfloat(x,-1)

eps(x::FloatingPoint) = isfinite(x) ? abs(nextfloat(x)-x) : nan(x)
eps(::Type{Float16}) = $(box(Float16,unbox(Uint16,0x1400)))
eps(::Type{Float32}) = $(box(Float32,unbox(Uint32,0x34000000)))
Expand Down
19 changes: 15 additions & 4 deletions test/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1162,22 +1162,22 @@ end
@test iround(Int, 0.5) == 1
@test iround(Int, prevfloat(0.5)) == 0
@test iround(Int, -0.5) == -1
@test iround(Int, prevfloat(-0.5)) == 0
@test iround(Int, nextfloat(-0.5)) == 0

@test iround(Uint, 0.5) == 1
@test iround(Uint, prevfloat(0.5)) == 0
@test_throws iround(Uint, -0.5)
@test iround(Uint, prevfloat(-0.5)) == 0
@test iround(Uint, nextfloat(-0.5)) == 0

@test iround(Int, 0.5f0) == 1
@test iround(Int, prevfloat(0.5f0)) == 0
@test iround(Int, -0.5f0) == -1
@test iround(Int, prevfloat(-0.5f0)) == 0
@test iround(Int, nextfloat(-0.5f0)) == 0

@test iround(Uint, 0.5f0) == 1
@test iround(Uint, prevfloat(0.5f0)) == 0
@test_throws iround(Uint, -0.5f0)
@test iround(Uint, prevfloat(-0.5f0)) == 0
@test iround(Uint, nextfloat(-0.5f0)) == 0

# numbers that can't be rounded by trunc(x+0.5)
@test iround(Int64, 2.0^52 + 1) == 4503599627370497
Expand Down Expand Up @@ -1579,3 +1579,14 @@ end

@test nextprod([2,3,5],30) == 30
@test nextprod([2,3,5],33) == 36

@test nextfloat(0.0) == 5.0e-324
@test prevfloat(0.0) == -5.0e-324
@test nextfloat(-0.0) == 5.0e-324
@test prevfloat(-0.0) == -5.0e-324
@test nextfloat(-5.0e-324) == 0.0
@test prevfloat(5.0e-324) == 0.0
@test nextfloat(-1.0) > -1.0
@test prevfloat(-1.0) < -1.0
@test nextfloat(nextfloat(0.0),-2) == -5.0e-324
@test nextfloat(prevfloat(0.0), 2) == 5.0e-324

0 comments on commit 72400ea

Please sign in to comment.