Skip to content

Commit d60837f

Browse files
authored
irrationals: restrict assume effects annotations to known types (#55886)
Other changes: * replace `:total` with the less powerful `:foldable` * add an `<:Integer` dispatch constraint on the `rationalize` method, closes #55872 * replace `Rational{<:Integer}` with just `Rational`, they're equal Other issues, related to `BigFloat` precision, are still present in irrationals.jl, to be fixed by followup PRs, including #55853. Fixes #55874
1 parent 224ff57 commit d60837f

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

base/irrationals.jl

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ AbstractFloat(x::AbstractIrrational) = Float64(x)::Float64
5151
Float16(x::AbstractIrrational) = Float16(Float32(x)::Float32)
5252
Complex{T}(x::AbstractIrrational) where {T<:Real} = Complex{T}(T(x))
5353

54-
# XXX this may change `DEFAULT_PRECISION`, thus not effect free
55-
@assume_effects :total function Rational{T}(x::AbstractIrrational) where T<:Integer
54+
function _irrational_to_rational(::Type{T}, x::AbstractIrrational) where T<:Integer
5655
o = precision(BigFloat)
5756
p = 256
5857
while true
@@ -66,13 +65,16 @@ Complex{T}(x::AbstractIrrational) where {T<:Real} = Complex{T}(T(x))
6665
p += 32
6766
end
6867
end
69-
Rational{BigInt}(x::AbstractIrrational) = throw(ArgumentError("Cannot convert an AbstractIrrational to a Rational{BigInt}: use rationalize(BigInt, x) instead"))
68+
Rational{T}(x::AbstractIrrational) where {T<:Integer} = _irrational_to_rational(T, x)
69+
_throw_argument_error_irrational_to_rational_bigint() = throw(ArgumentError("Cannot convert an AbstractIrrational to a Rational{BigInt}: use rationalize(BigInt, x) instead"))
70+
Rational{BigInt}(::AbstractIrrational) = _throw_argument_error_irrational_to_rational_bigint()
7071

71-
@assume_effects :total function (t::Type{T})(x::AbstractIrrational, r::RoundingMode) where T<:Union{Float32,Float64}
72+
function _irrational_to_float(::Type{T}, x::AbstractIrrational, r::RoundingMode) where T<:Union{Float32,Float64}
7273
setprecision(BigFloat, 256) do
7374
T(BigFloat(x)::BigFloat, r)
7475
end
7576
end
77+
(::Type{T})(x::AbstractIrrational, r::RoundingMode) where {T<:Union{Float32,Float64}} = _irrational_to_float(T, x, r)
7678

7779
float(::Type{<:AbstractIrrational}) = Float64
7880

@@ -110,14 +112,18 @@ end
110112
<=(x::AbstractFloat, y::AbstractIrrational) = x < y
111113

112114
# Irrational vs Rational
113-
@assume_effects :total function rationalize(::Type{T}, x::AbstractIrrational; tol::Real=0) where T
115+
function _rationalize_irrational(::Type{T}, x::AbstractIrrational, tol::Real) where {T<:Integer}
114116
return rationalize(T, big(x), tol=tol)
115117
end
116-
@assume_effects :total function lessrational(rx::Rational{<:Integer}, x::AbstractIrrational)
117-
# an @assume_effects :total version of `<` for determining if the rationalization of
118-
# an irrational number required rounding up or down
118+
function rationalize(::Type{T}, x::AbstractIrrational; tol::Real=0) where {T<:Integer}
119+
return _rationalize_irrational(T, x, tol)
120+
end
121+
function _lessrational(rx::Rational, x::AbstractIrrational)
119122
return rx < big(x)
120123
end
124+
function lessrational(rx::Rational, x::AbstractIrrational)
125+
return _lessrational(rx, x)
126+
end
121127
function <(x::AbstractIrrational, y::Rational{T}) where T
122128
T <: Unsigned && x < 0.0 && return true
123129
rx = rationalize(T, x)

base/mathconstants.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,26 @@ Base.@irrational γ euler
1616
Base.@irrational φ (1+sqrt(big(5)))/2
1717
Base.@irrational catalan catalan
1818

19+
const _KnownIrrational = Union{
20+
typeof(π), typeof(ℯ), typeof(γ), typeof(φ), typeof(catalan)
21+
}
22+
23+
function Rational{BigInt}(::_KnownIrrational)
24+
Base._throw_argument_error_irrational_to_rational_bigint()
25+
end
26+
Base.@assume_effects :foldable function Rational{T}(x::_KnownIrrational) where {T<:Integer}
27+
Base._irrational_to_rational(T, x)
28+
end
29+
Base.@assume_effects :foldable function (::Type{T})(x::_KnownIrrational, r::RoundingMode) where {T<:Union{Float32,Float64}}
30+
Base._irrational_to_float(T, x, r)
31+
end
32+
Base.@assume_effects :foldable function rationalize(::Type{T}, x::_KnownIrrational; tol::Real=0) where {T<:Integer}
33+
Base._rationalize_irrational(T, x, tol)
34+
end
35+
Base.@assume_effects :foldable function Base.lessrational(rx::Rational, x::_KnownIrrational)
36+
Base._lessrational(rx, x)
37+
end
38+
1939
# aliases
2040
"""
2141
π

0 commit comments

Comments
 (0)