Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix inf and nan bugs #204

Merged
merged 1 commit into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/math/elementary/explog.jl
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ end

function log1p(x::DoubleFloat{T}) where {T<:IEEEFloat}
isnan(x) && return x
isinf(x) && !signbit(x) && return
isinf(x) && !signbit(x) && return x
u = 1.0 + x
if u == one(DoubleFloat{T})
x
Expand Down
2 changes: 1 addition & 1 deletion src/math/ops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ isnotfinite(x::Float32) = reinterpret(UInt32,x) & 0x7f800000 === 0x7f800000
isqnan(x::Float32) = reinterpret(UInt32,x) & 0x7fc00000 === 0x7fc00000
isainf(x::Float32) = reinterpret(UInt32,x) & 0x7fc00000 === 0x7f800000

isnotfinite(x::DoubleFloat{T}) where {T<:IEEEFloat} = isnan(LO(x))
isnotfinite(x::DoubleFloat{T}) where {T<:IEEEFloat} = !isfinite(HI(x))
isqnan(x::DoubleFloat{T}) where {T<:IEEEFloat} = isqnan(HI(x))
isainf(x::DoubleFloat{T}) where {T<:IEEEFloat} = isainf(HI(x))

Expand Down
16 changes: 8 additions & 8 deletions src/math/ops/op_dbdb_db.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,41 @@ Base.:(/)(x::Tuple{T,T}, y::DoubleFloat{T}) where {T<:IEEEFloat} = DoubleFloat{T


@inline function add_dbdb_db(x::DoubleFloat{T}, y::DoubleFloat{T}) where {T<:IEEEFloat}
(isnan(LO(x)) | isnan(LO(y))) && return add_dbdb_db_nonfinite(x,y)
(isnotfinite(x) | isnotfinite(y)) && return add_dbdb_db_nonfinite(x,y)
return DoubleFloat{T}(add_dddd_dd(HILO(x), HILO(y)))
end

@inline function sub_dbdb_db(x::DoubleFloat{T}, y::DoubleFloat{T}) where {T<:IEEEFloat}
(isnan(LO(x)) | isnan(LO(y))) && return sub_dbdb_db_nonfinite(x,y)
(isnotfinite(x) | isnotfinite(y)) && return sub_dbdb_db_nonfinite(x,y)
return DoubleFloat{T}(sub_dddd_dd(HILO(x), HILO(y)))
end

@inline function mul_dbdb_db(x::DoubleFloat{T}, y::DoubleFloat{T}) where {T<:IEEEFloat}
(isnan(LO(x)) | isnan(LO(y))) && return mul_dbdb_db_nonfinite(x,y)
(isnotfinite(x) | isnotfinite(y)) && return mul_dbdb_db_nonfinite(x,y)
return DoubleFloat{T}(mul_dddd_dd(HILO(x), HILO(y)))
end

@inline function dvi_dbdb_db(x::DoubleFloat{T}, y::DoubleFloat{T}) where {T<:IEEEFloat}
(iszero(HI(y)) | isnan(LO(x)) | isnan(LO(y))) && return dvi_dbdb_db_nonfinite(x,y)
(iszero(HI(y)) | isnotfinite(x) | isnotfinite(y)) && return dvi_dbdb_db_nonfinite(x,y)
return DoubleFloat{T}(dvi_dddd_dd(HILO(x), HILO(y)))
end

@inline function add_dbdb_db_nonfinite(x::DoubleFloat{T}, y::DoubleFloat{T}) where {T<:IEEEFloat}
z = HI(x) + HI(y)
return DoubleFloat{T}(z, T(NaN))
return DoubleFloat{T}(z, z)
end

@inline function sub_dbdb_db_nonfinite(x::DoubleFloat{T}, y::DoubleFloat{T}) where {T<:IEEEFloat}
z = HI(x) - HI(y)
return DoubleFloat{T}(z, T(NaN))
return DoubleFloat{T}(z, z)
end

@inline function mul_dbdb_db_nonfinite(x::DoubleFloat{T}, y::DoubleFloat{T}) where {T<:IEEEFloat}
z = HI(x) * HI(y)
return DoubleFloat{T}(z, T(NaN))
return DoubleFloat{T}(z, z)
end

@inline function dvi_dbdb_db_nonfinite(x::DoubleFloat{T}, y::DoubleFloat{T}) where {T<:IEEEFloat}
z = HI(x) / HI(y)
return DoubleFloat{T}(z, T(NaN))
return DoubleFloat{T}(z, z)
end
16 changes: 8 additions & 8 deletions src/math/ops/op_dbfp_db.jl
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
@inline function add_dbfp_db(x::DoubleFloat{T}, y::T) where {T<:IEEEFloat}
(isqnan(LO(x)) | isnotfinite(y)) && return add_dbfp_db_nonfinite(x,y)
(isnotfinite(x) | isnotfinite(y)) && return add_dbfp_db_nonfinite(x,y)
return DoubleFloat{T}(add_ddfp_dd(HILO(x), y))
end

@inline function sub_dbfp_db(x::DoubleFloat{T}, y::T) where {T<:IEEEFloat}
(isqnan(LO(x)) | isnotfinite(y)) && return sub_dbfp_db_nonfinite(x,y)
(isnotfinite(x) | isnotfinite(y)) && return sub_dbfp_db_nonfinite(x,y)
return DoubleFloat{T}(sub_ddfp_dd(HILO(x), y))
end

@inline function mul_dbfp_db(x::DoubleFloat{T}, y::T) where {T<:IEEEFloat}
(isqnan(LO(x)) | isnotfinite(y)) && return mul_dbfp_db_nonfinite(x,y)
(isnotfinite(x) | isnotfinite(y)) && return mul_dbfp_db_nonfinite(x,y)
return DoubleFloat{T}(mul_ddfp_dd(HILO(x), y))
end

@inline function dvi_dbfp_db(x::DoubleFloat{T}, y::T) where {T<:IEEEFloat}
(isqnan(LO(x)) | isnotfinite(y)) && return dvi_dbfp_db_nonfinite(x,y)
(isnotfinite(x) | isnotfinite(y)) && return dvi_dbfp_db_nonfinite(x,y)
return DoubleFloat{T}(dvi_ddfp_dd(HILO(x), y))
end

@inline function add_dbfp_db_nonfinite(x::DoubleFloat{T}, y::T) where {T<:IEEEFloat}
z = HI(x) + y
return DoubleFloat{T}(z, T(NaN))
return DoubleFloat{T}(z, z)

Check warning on line 23 in src/math/ops/op_dbfp_db.jl

View check run for this annotation

Codecov / codecov/patch

src/math/ops/op_dbfp_db.jl#L23

Added line #L23 was not covered by tests
end

@inline function sub_dbfp_db_nonfinite(x::DoubleFloat{T}, y::T) where {T<:IEEEFloat}
z = HI(x) - y
return DoubleFloat{T}(z, T(NaN))
return DoubleFloat{T}(z, z)

Check warning on line 28 in src/math/ops/op_dbfp_db.jl

View check run for this annotation

Codecov / codecov/patch

src/math/ops/op_dbfp_db.jl#L28

Added line #L28 was not covered by tests
end

@inline function mul_dbfp_db_nonfinite(x::DoubleFloat{T}, y::T) where {T<:IEEEFloat}
z = HI(x) * y
return DoubleFloat{T}(z, T(NaN))
return DoubleFloat{T}(z, z)

Check warning on line 33 in src/math/ops/op_dbfp_db.jl

View check run for this annotation

Codecov / codecov/patch

src/math/ops/op_dbfp_db.jl#L33

Added line #L33 was not covered by tests
end

@inline function dvi_dbfp_db_nonfinite(x::DoubleFloat{T}, y::T) where {T<:IEEEFloat}
z = HI(x) / y
return DoubleFloat{T}(z, T(NaN))
return DoubleFloat{T}(z, z)

Check warning on line 38 in src/math/ops/op_dbfp_db.jl

View check run for this annotation

Codecov / codecov/patch

src/math/ops/op_dbfp_db.jl#L38

Added line #L38 was not covered by tests
end
5 changes: 3 additions & 2 deletions src/math/ops/op_dd_dd.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ end
end

function sqrt_dd_dd(x::Tuple{T,T}) where {T<:IEEEFloat}
iszero(HI(x)) && return x
signbit(HI(x)) && throw(DomainError("sqrt(x) expects x >= 0"))
(isnan(HI(x)) | iszero(HI(x))) && return x
signbit(HI(x)) && Base.Math.throw_complex_domainerror(:sqrt, HI(x))
isinf(HI(x)) && return x

ahi, alo = HILO(x)
s = sqrt(ahi)
Expand Down
16 changes: 8 additions & 8 deletions src/math/ops/op_fpdb_db.jl
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
@inline function add_fpdb_db(x::T, y::DoubleFloat{T}) where {T<:IEEEFloat}
(isnotfinite(x) | isqnan(LO(y))) && return add_fpdb_db_nonfinite(x,y)
(isnotfinite(x) | isnotfinite(y)) && return add_fpdb_db_nonfinite(x,y)
return DoubleFloat{T}(add_fpdd_dd(x, HILO(y)))
end

@inline function sub_fpdb_db(x::T, y::DoubleFloat{T}) where {T<:IEEEFloat}
(isnotfinite(x) | isqnan(LO(y))) && return sub_fpdb_db_nonfinite(x,y)
(isnotfinite(x) | isnotfinite(y)) && return sub_fpdb_db_nonfinite(x,y)
return DoubleFloat{T}(sub_fpdd_dd(x, HILO(y)))
end

@inline function mul_fpdb_db(x::T, y::DoubleFloat{T}) where {T<:IEEEFloat}
(isnotfinite(x) | isqnan(LO(y))) && return mul_fpdb_db_nonfinite(x,y)
(isnotfinite(x) | isnotfinite(y)) && return mul_fpdb_db_nonfinite(x,y)
return DoubleFloat{T}(mul_fpdd_dd(x, HILO(y)))
end

@inline function dvi_fpdb_db(x::T, y::DoubleFloat{T}) where {T<:IEEEFloat}
(isnotfinite(x) | isqnan(LO(y))) && return dvi_fpdb_db_nonfinite(x,y)
(isnotfinite(x) | isnotfinite(y)) && return dvi_fpdb_db_nonfinite(x,y)

Check warning on line 17 in src/math/ops/op_fpdb_db.jl

View check run for this annotation

Codecov / codecov/patch

src/math/ops/op_fpdb_db.jl#L17

Added line #L17 was not covered by tests
return DoubleFloat{T}(dvi_fpdd_dd(x, HILO(y)))
end

@inline function add_fpdb_db_nonfinite(x::T, y::DoubleFloat{T}) where {T<:IEEEFloat}
z = x + HI(y)
return DoubleFloat{T}(z, T(NaN))
return DoubleFloat{T}(z, z)

Check warning on line 23 in src/math/ops/op_fpdb_db.jl

View check run for this annotation

Codecov / codecov/patch

src/math/ops/op_fpdb_db.jl#L23

Added line #L23 was not covered by tests
end

@inline function sub_fpdb_db_nonfinite(x::T, y::DoubleFloat{T}) where {T<:IEEEFloat}
z = x - HI(y)
return DoubleFloat{T}(z, T(NaN))
return DoubleFloat{T}(z, z)

Check warning on line 28 in src/math/ops/op_fpdb_db.jl

View check run for this annotation

Codecov / codecov/patch

src/math/ops/op_fpdb_db.jl#L28

Added line #L28 was not covered by tests
end

@inline function mul_fpdb_db_nonfinite(x::T, y::DoubleFloat{T}) where {T<:IEEEFloat}
z = x * HI(y)
return DoubleFloat{T}(z, T(NaN))
return DoubleFloat{T}(z, z)

Check warning on line 33 in src/math/ops/op_fpdb_db.jl

View check run for this annotation

Codecov / codecov/patch

src/math/ops/op_fpdb_db.jl#L33

Added line #L33 was not covered by tests
end

@inline function dvi_fpdb_db_nonfinite(x::T, y::DoubleFloat{T}) where {T<:IEEEFloat}
z = x / HI(y)
return DoubleFloat{T}(z, T(NaN))
return DoubleFloat{T}(z, z)

Check warning on line 38 in src/math/ops/op_fpdb_db.jl

View check run for this annotation

Codecov / codecov/patch

src/math/ops/op_fpdb_db.jl#L38

Added line #L38 was not covered by tests
end
6 changes: 3 additions & 3 deletions src/type/predicates.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
""""
"""
__Predicates__ are functions that ask "yes or no" questions of their argument[s].
You can ask of a number "Is this zero?" or "Is this one?" and these predicates
(`iszero`, `isone`) will work as expected with almost all numerical types.
Expand Down Expand Up @@ -87,10 +87,10 @@ isinf(x::DoubleFloat{T}) where {T<:IEEEFloat} =
"""
isposinf(x)

Tests whether a number positive and infinite.
Tests whether a number is positive and infinite.
"""
isposinf(x::DoubleFloat{T}) where {T<:IEEEFloat} =
isinf(HI(x))
isinf(HI(x)) && !signbit(HI(x))

"""
isneginf(x)
Expand Down
6 changes: 3 additions & 3 deletions src/type/specialvalues.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ zero(::Type{DoubleFloat{T}}) where {T<:IEEEFloat} = DoubleFloat{T}(zero(T), zero
one(::Type{DoubleFloat{T}}) where {T<:IEEEFloat} = DoubleFloat{T}(one(T), zero(T))

nan(::Type{DoubleFloat{T}}) where {T<:IEEEFloat} = DoubleFloat{T}(T(NaN), T(NaN))
inf(::Type{DoubleFloat{T}}) where {T<:IEEEFloat} = DoubleFloat{T}(T(Inf), T(NaN))
posinf(::Type{DoubleFloat{T}}) where {T<:IEEEFloat} = DoubleFloat{T}(T(Inf), T(NaN))
neginf(::Type{DoubleFloat{T}}) where {T<:IEEEFloat} = DoubleFloat{T}(T(-Inf), T(NaN))
inf(::Type{DoubleFloat{T}}) where {T<:IEEEFloat} = DoubleFloat{T}(T(Inf), T(Inf))
posinf(::Type{DoubleFloat{T}}) where {T<:IEEEFloat} = DoubleFloat{T}(T(Inf), T(Inf))
neginf(::Type{DoubleFloat{T}}) where {T<:IEEEFloat} = DoubleFloat{T}(T(-Inf), T(-Inf))

typemax(::Type{DoubleFloat{T}}) where {T<:IEEEFloat} = DoubleFloat{T}(typemax(T))
typemin(::Type{DoubleFloat{T}}) where {T<:IEEEFloat} = DoubleFloat{T}(typemin(T))
Expand Down
15 changes: 15 additions & 0 deletions test/specialvalues.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ end
@test isinf(T(Inf)) == isinf(inf(T))
@test isinf(T(Inf)) == isposinf(posinf(T))
@test isinf(T(-Inf)) == isneginf(neginf(T))
@test isinf(T(-Inf)) == !isposinf(neginf(T))
@test isnan(T(NaN)) == isnan(nan(T))

@test isinf(T(Inf32)) == isinf(inf(T))
@test isinf(T(Inf32)) == isposinf(posinf(T))
@test isinf(T(-Inf32)) == isneginf(neginf(T))
@test isinf(T(-Inf32)) == !isposinf(neginf(T))
@test isnan(T(NaN32)) == isnan(nan(T))

@test isinf(T(Inf16)) == isinf(inf(T))
@test isinf(T(Inf16)) == isposinf(posinf(T))
@test isinf(T(-Inf16)) == isneginf(neginf(T))
@test isinf(T(-Inf16)) == !isposinf(neginf(T))
@test isnan(T(NaN16)) == isnan(nan(T))
end

Expand Down Expand Up @@ -76,6 +79,18 @@ end
@test isnan(asech(T(NaN)))
@test isnan(acoth(T(NaN)))
end

@testset "Inf and NaN function values $T" for T in (Double16, Double32, Double64)
@test isnan(sqrt(T(0)/T(0)))
@test isinf(sqrt(T(Inf)))
@test isinf(exp(T(Inf)))
@test isinf(log(T(Inf)))
@test isinf(log2(T(Inf)))
@test isinf(log10(T(Inf)))
@test isinf(log1p(T(Inf)))
@test isinf(T(Inf)*T(1))
@test isinf(T(1)*T(Inf))
end

@testset "floatmin2 $T" for T in (Double16, Double32, Double64)
trueval = (twopar = 2one(T); twopar^trunc(Integer,log(floatmin(T)/eps(T))/log(twopar)/twopar))
Expand Down
Loading