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

Generic frexp #150

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
18 changes: 15 additions & 3 deletions src/math/prearith/prearith.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,33 @@ end
flipsign(x::DoubleFloat{T}, y::U) where {T<:IEEEFloat, U<:Unsigned} = +x
copysign(x::DoubleFloat{T}, y::U) where {T<:IEEEFloat, U<:Unsigned} = +x

function Base.Math.frexp(x::DoubleFloat{T}) where {T<:IEEEFloat}
"""
frexps(x::DoubleFloat)

Applies `Base.frexp` to both `hi` and `lo` parts, and returns a tuple of tuples.
See also `DoubleFloats.ldexps` for the inverse, and `DoubleFloats.signs` similar tuple.
"""
function frexps(x::DoubleFloat{T}) where {T<:IEEEFloat}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit of an awful name, trying to match signs. Could be more explicit like double_frexp or something.

frhi, exphi = frexp(HI(x))
frlo, explo = frexp(LO(x))
return (frhi, exphi), (frlo, explo)
end

function Base.Math.frexp(x::DoubleFloat{T}) where {T<:IEEEFloat}
frhi, exphi = frexp(HI(x))
frlo, explo = frexp(LO(x))
return DoubleFloat{T}(frhi, ldexp(frlo, explo - exphi)), exphi
end

function Base.Math.ldexp(x::DoubleFloat{T}, exponent::I) where {T<:IEEEFloat, I<:Integer}
return DoubleFloat{T}(ldexp(HI(x), exponent), ldexp(LO(x), exponent))
end

function Base.Math.ldexp(dhi::Tuple{T,I}, dlo::Tuple{T,I}) where {T<:IEEEFloat, I<:Integer}
function ldexps(dhi::Tuple{T,I}, dlo::Tuple{T,I}) where {T<:IEEEFloat, I<:Integer}
return DoubleFloat(ldexp(dhi[1], dhi[2]), ldexp(dlo[1], dlo[2]))
end

function Base.Math.ldexp(dhilo::Tuple{Tuple{T,I}, Tuple{T,I}}) where {T<:IEEEFloat, I<:Integer}
function ldexps(dhilo::Tuple{Tuple{T,I}, Tuple{T,I}}) where {T<:IEEEFloat, I<:Integer}
return ldexp(dhilo[1], dhilo[2])
end

Expand Down
18 changes: 14 additions & 4 deletions test/prearith.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,22 @@
@test flipsign(negval, 1) == negval
@test copysign(val, -1) == negval
@test copysign(negval, 1) == val

@test ldexp(frexp(val)...,) == val
# @test ldexp(significand(val), exponent(val)) == val

@test signs(val) == (sign(HI(val)), sign(LO(val)))
fr, ex = frexp(val)
@test fr * T(2)^ex == val

@test fr ≈ frexp(Float64(val))[1]
@test ex == frexp(Float64(val))[2]

@test isnan(frexp(T(NaN))[1])
@test isinf(frexp(T(Inf))[1])
@test iszero(frexp(T(0))[1])

@test DoubleFloats.ldexps(DoubleFloats.frexps(val)...,) == val
# @test ldexp(significand(val), exponent(val)) == val

@test signs(val) == (sign(HI(val)), sign(LO(val)))
end

@testset "trunc $T" for T in (Double16, Double32, Double64)
Expand Down