Skip to content

Commit

Permalink
Fix conversion Irrational => Rational
Browse files Browse the repository at this point in the history
Fixes #16513.
  • Loading branch information
simonbyrne committed Jun 25, 2016
1 parent dcde84d commit da37da9
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 3 deletions.
25 changes: 22 additions & 3 deletions base/irrationals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,30 @@ promote_rule{s,T<:Number}(::Type{Irrational{s}}, ::Type{T}) = promote_type(Float
convert(::Type{AbstractFloat}, x::Irrational) = Float64(x)
convert(::Type{Float16}, x::Irrational) = Float16(Float32(x))
convert{T<:Real}(::Type{Complex{T}}, x::Irrational) = convert(Complex{T}, convert(T,x))
convert{T<:Integer}(::Type{Rational{T}}, x::Irrational) = convert(Rational{T}, Float64(x))

# NOTE: We use a @generated functions to compute the constants.
# Hopefully in future we can replace this with @pure.
# These return values which can be spliced directly into the AST.
@generated function convert{T<:Integer}(::Type{Rational{T}}, x::Irrational)
o = precision(BigFloat)
p = 256
while true
setprecision(BigFloat, p)
bx = BigFloat(x())
r = rationalize(T, bx, tol=0)
if abs(BigFloat(r) - bx) > eps(bx)
setprecision(BigFloat, o)
return r
end
p += 32
end
end
convert(::Type{Rational{BigInt}}, x::Irrational) = throw(ArgumentError("Cannot convert an Irrational to a Rational{BigInt}: use rationalize(Rational{BigInt}, x) instead"))

@generated function (t::Type{T}){T<:Union{Float32,Float64},s}(c::Irrational{s},r::RoundingMode)
f = T(big(c()),r())
:($f)
setprecision(BigFloat, 256) do
T(big(c()),r())
end
end

=={s}(::Irrational{s}, ::Irrational{s}) = true
Expand Down
6 changes: 6 additions & 0 deletions test/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2086,6 +2086,12 @@ for f in (trunc, round, floor, ceil)

@test isa(convert(Float64, big(1)//2), Float64)

# issue 16513
@test convert(Rational{Int32}, pi) == 1068966896 // 340262731
@test convert(Rational{Int64}, pi) == 2646693125139304345 // 842468587426513207
@test convert(Rational{Int128}, pi) == 60728338969805745700507212595448411044 // 19330430665609526556707216376512714945
@test_throws ArgumentError convert(Rational{BigInt}, pi)

# issue 5935
@test rationalize(Int8, nextfloat(0.1)) == 1//10
@test rationalize(Int64, nextfloat(0.1)) == 300239975158034//3002399751580339
Expand Down

0 comments on commit da37da9

Please sign in to comment.