From 861100c15b050885297430e7afc24c7a638de982 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Mon, 27 Jun 2016 12:47:15 -0400 Subject: [PATCH] Fix conversion Irrational => Rational (#16527) Fixes #16513. Changes generated macro to pure macro, so as to avoid breaking in future compiler changes. --- base/irrationals.jl | 24 ++++++++++++++++++++---- test/numbers.jl | 6 ++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/base/irrationals.jl b/base/irrationals.jl index 794d0ec91a748..e4347f6b8dedd 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -13,11 +13,27 @@ 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)) -@generated function (t::Type{T}){T<:Union{Float32,Float64},s}(c::Irrational{s},r::RoundingMode) - f = T(big(c()),r()) - :($f) +@pure 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")) + +@pure function (t::Type{T}){T<:Union{Float32,Float64}}(x::Irrational, r::RoundingMode) + setprecision(BigFloat, 256) do + T(BigFloat(x), r) + end end =={s}(::Irrational{s}, ::Irrational{s}) = true diff --git a/test/numbers.jl b/test/numbers.jl index f8377601f7ad2..550cc6981639a 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2082,6 +2082,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