diff --git a/base/float.jl b/base/float.jl index d26d279e47895..5e40652490835 100644 --- a/base/float.jl +++ b/base/float.jl @@ -836,12 +836,12 @@ number of significand digits in that base. """ function precision end -_precision(::Type{Float16}) = 11 -_precision(::Type{Float32}) = 24 -_precision(::Type{Float64}) = 53 -function _precision(x, base::Integer=2) +_precision_with_base_2(::Type{Float16}) = 11 +_precision_with_base_2(::Type{Float32}) = 24 +_precision_with_base_2(::Type{Float64}) = 53 +function _precision(x, base::Integer) base > 1 || throw(DomainError(base, "`base` cannot be less than 2.")) - p = _precision(x) + p = _precision_with_base_2(x) return base == 2 ? Int(p) : floor(Int, p / log2(base)) end precision(::Type{T}; base::Integer=2) where {T<:AbstractFloat} = _precision(T, base) diff --git a/base/mpfr.jl b/base/mpfr.jl index 276fd430ff1e0..c12154fa517c3 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -16,7 +16,7 @@ import cosh, sinh, tanh, sech, csch, coth, acosh, asinh, atanh, lerpi, cbrt, typemax, typemin, unsafe_trunc, floatmin, floatmax, rounding, setrounding, maxintfloat, widen, significand, frexp, tryparse, iszero, - isone, big, _string_n, decompose, minmax, + isone, big, _string_n, decompose, minmax, _precision_with_base_2, sinpi, cospi, sincospi, tanpi, sind, cosd, tand, asind, acosd, atand, uinttype, exponent_max, exponent_min, ieee754_representation, significand_mask, RawBigIntRoundingIncrementHelper, truncated, RawBigInt @@ -221,7 +221,7 @@ widen(::Type{Float64}) = BigFloat widen(::Type{BigFloat}) = BigFloat function BigFloat(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) - if precision == _precision(x) + if precision == _precision_with_base_2(x) return x else z = BigFloat(;precision=precision) @@ -232,7 +232,7 @@ function BigFloat(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::I end function _duplicate(x::BigFloat) - z = BigFloat(;precision=_precision(x)) + z = BigFloat(;precision=_precision_with_base_2(x)) ccall((:mpfr_set, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, 0) return z end @@ -954,12 +954,12 @@ function sign(x::BigFloat) return c < 0 ? -one(x) : one(x) end -function _precision(x::BigFloat) # precision of an object of type BigFloat +function _precision_with_base_2(x::BigFloat) # precision of an object of type BigFloat return ccall((:mpfr_get_prec, libmpfr), Clong, (Ref{BigFloat},), x) end precision(x::BigFloat; base::Integer=2) = _precision(x, base) -_precision(::Type{BigFloat}) = Int(DEFAULT_PRECISION[]) # default precision of the type BigFloat itself +_precision_with_base_2(::Type{BigFloat}) = Int(DEFAULT_PRECISION[]) # default precision of the type BigFloat itself """ setprecision([T=BigFloat,] precision::Int; base=2) diff --git a/test/numbers.jl b/test/numbers.jl index a9d126aa33d5a..a50ce5f85df0e 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -3141,3 +3141,26 @@ end @test n == G(F(n)) == F(G(n)) end end + +@testset "`precision`" begin + Fs = (Float16, Float32, Float64, BigFloat) + + @testset "type vs instance" begin + @testset "F: $F" for F ∈ Fs + @test precision(F) == precision(one(F)) + @test precision(F, base = 2) == precision(one(F), base = 2) + @test precision(F, base = 3) == precision(one(F), base = 3) + end + end + + @testset "`precision` of `Union` shouldn't recur infinitely, #52909" begin + @testset "i: $i" for i ∈ eachindex(Fs) + @testset "j: $j" for j ∈ (i + 1):lastindex(Fs) + S = Fs[i] + T = Fs[j] + @test_throws MethodError precision(Union{S,T}) + @test_throws MethodError precision(Union{S,T}, base = 3) + end + end + end +end