diff --git a/NEWS.md b/NEWS.md index d650733551474..dbacdc77229ec 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,6 +10,8 @@ New language features Language changes ---------------- + * the constructor `BigFloat(::BigFloat)` now respects the global precision setting and always + returns a `BigFloat` with precision equal to `precision(BigFloat)` ([#29127]). * Parser inputs ending with a comma are now consistently treated as incomplete. Previously they were sometimes parsed as tuples, depending on whitespace ([#28506]). diff --git a/base/mpfr.jl b/base/mpfr.jl index 2d5acf2605d48..504d63ee59a1f 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -116,7 +116,17 @@ BigFloat(x) widen(::Type{Float64}) = BigFloat widen(::Type{BigFloat}) = BigFloat -BigFloat(x::BigFloat) = x +function BigFloat(x::BigFloat) + if precision(BigFloat) == precision(x) + x + else + z = BigFloat() + ccall((:mpfr_set, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), + z, x, ROUNDING_MODE[]) + z + end +end + # convert to BigFloat for (fJ, fC) in ((:si,:Clong), (:ui,:Culong)) diff --git a/test/mpfr.jl b/test/mpfr.jl index bfb16a6ce2995..3e69762caf081 100644 --- a/test/mpfr.jl +++ b/test/mpfr.jl @@ -35,6 +35,20 @@ import Base.MPFR @test typeof(BigFloat(1//1)) == BigFloat @test typeof(BigFloat(one(Rational{BigInt}))) == BigFloat + + # BigFloat constructor respects global precision when not specified + let prec = precision(BigFloat) < 16 ? 256 : precision(BigFloat) ÷ 2 + xs = Real[T(1) for T in (Int, BigInt, Float32, Float64, BigFloat)] + f = xs[end] + @test BigFloat(f) === f # no-op when precision of operand is the same as global's one + setprecision(prec) do + @test precision(xs[end]) != prec + for x in xs + @test precision(BigFloat(x)) == prec + @test precision(BigFloat(x, prec ÷ 2)) == prec ÷ 2 + end + end + end end @testset "basic arithmetic" begin tol = 1e-12