Skip to content

Commit 861100c

Browse files
simonbyrneStefanKarpinski
authored andcommitted
Fix conversion Irrational => Rational (#16527)
Fixes #16513. Changes generated macro to pure macro, so as to avoid breaking in future compiler changes.
1 parent 6c4429b commit 861100c

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

base/irrationals.jl

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,27 @@ promote_rule{s,T<:Number}(::Type{Irrational{s}}, ::Type{T}) = promote_type(Float
1313
convert(::Type{AbstractFloat}, x::Irrational) = Float64(x)
1414
convert(::Type{Float16}, x::Irrational) = Float16(Float32(x))
1515
convert{T<:Real}(::Type{Complex{T}}, x::Irrational) = convert(Complex{T}, convert(T,x))
16-
convert{T<:Integer}(::Type{Rational{T}}, x::Irrational) = convert(Rational{T}, Float64(x))
1716

18-
@generated function (t::Type{T}){T<:Union{Float32,Float64},s}(c::Irrational{s},r::RoundingMode)
19-
f = T(big(c()),r())
20-
:($f)
17+
@pure function convert{T<:Integer}(::Type{Rational{T}}, x::Irrational)
18+
o = precision(BigFloat)
19+
p = 256
20+
while true
21+
setprecision(BigFloat, p)
22+
bx = BigFloat(x)
23+
r = rationalize(T, bx, tol=0)
24+
if abs(BigFloat(r) - bx) > eps(bx)
25+
setprecision(BigFloat, o)
26+
return r
27+
end
28+
p += 32
29+
end
30+
end
31+
convert(::Type{Rational{BigInt}}, x::Irrational) = throw(ArgumentError("Cannot convert an Irrational to a Rational{BigInt}: use rationalize(Rational{BigInt}, x) instead"))
32+
33+
@pure function (t::Type{T}){T<:Union{Float32,Float64}}(x::Irrational, r::RoundingMode)
34+
setprecision(BigFloat, 256) do
35+
T(BigFloat(x), r)
36+
end
2137
end
2238

2339
=={s}(::Irrational{s}, ::Irrational{s}) = true

test/numbers.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,6 +2082,12 @@ for f in (trunc, round, floor, ceil)
20822082

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

2085+
# issue 16513
2086+
@test convert(Rational{Int32}, pi) == 1068966896 // 340262731
2087+
@test convert(Rational{Int64}, pi) == 2646693125139304345 // 842468587426513207
2088+
@test convert(Rational{Int128}, pi) == 60728338969805745700507212595448411044 // 19330430665609526556707216376512714945
2089+
@test_throws ArgumentError convert(Rational{BigInt}, pi)
2090+
20852091
# issue 5935
20862092
@test rationalize(Int8, nextfloat(0.1)) == 1//10
20872093
@test rationalize(Int64, nextfloat(0.1)) == 300239975158034//3002399751580339

0 commit comments

Comments
 (0)