From 81676ec5899a8a7bd81abab931775a934d9a4567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Tue, 22 Jul 2025 20:55:57 +0200 Subject: [PATCH 1/6] Fix rounding when converting Rational to BigFloat --- base/mpfr.jl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index ee1e4eac39145..91f7c6e4ec3e2 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -391,13 +391,19 @@ BigFloat(x::Union{UInt8,UInt16,UInt32}, r::MPFRRoundingMode=rounding_raw(BigFloa BigFloat(x::Union{Float16,Float32}, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat)) = BigFloat(Float64(x), r; precision=precision) -function BigFloat(x::Rational, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat)) +function BigFloat(x::Rational, r::Base.MPFR.MPFRRoundingMode=Base.MPFR.MPFRRoundNearest; precision::Integer=_precision_with_base_2(BigFloat)) + r_den = _opposite_round(r) setprecision(BigFloat, precision) do - setrounding_raw(BigFloat, r) do - BigFloat(numerator(x))::BigFloat / BigFloat(denominator(x))::BigFloat + Base.MPFR.setrounding_raw(BigFloat, r) do + BigFloat(numerator(x))::BigFloat / BigFloat(denominator(x), r_den)::BigFloat end end end +function _opposite_round(r::Base.MPFR.MPFRRoundingMode) + r == MPFR.MPFRRoundUp && return MPFR.MPFRRoundDown + r == MPFR.MPFRRoundDown && return MPFR.MPFRRoundUp + return r +end function tryparse(::Type{BigFloat}, s::AbstractString; base::Integer=0, precision::Integer=_precision_with_base_2(BigFloat), rounding::MPFRRoundingMode=rounding_raw(BigFloat)) !isempty(s) && isspace(s[end]) && return tryparse(BigFloat, rstrip(s), base = base) From 0d914c47e779299fbfaa67987b0a31430dce627e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Tue, 22 Jul 2025 21:14:30 +0200 Subject: [PATCH 2/6] Update mpfr.jl --- base/mpfr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index 91f7c6e4ec3e2..b5ee0e08d209f 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -391,7 +391,7 @@ BigFloat(x::Union{UInt8,UInt16,UInt32}, r::MPFRRoundingMode=rounding_raw(BigFloa BigFloat(x::Union{Float16,Float32}, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat)) = BigFloat(Float64(x), r; precision=precision) -function BigFloat(x::Rational, r::Base.MPFR.MPFRRoundingMode=Base.MPFR.MPFRRoundNearest; precision::Integer=_precision_with_base_2(BigFloat)) +function BigFloat(x::Rational, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat)) r_den = _opposite_round(r) setprecision(BigFloat, precision) do Base.MPFR.setrounding_raw(BigFloat, r) do From 299fc8e5f26e5e2659ff65501e885d524afc525c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Tue, 22 Jul 2025 21:33:18 +0200 Subject: [PATCH 3/6] Minor cleanup --- base/mpfr.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index b5ee0e08d209f..cc2ed02df6b84 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -394,14 +394,14 @@ BigFloat(x::Union{Float16,Float32}, r::MPFRRoundingMode=rounding_raw(BigFloat); function BigFloat(x::Rational, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat)) r_den = _opposite_round(r) setprecision(BigFloat, precision) do - Base.MPFR.setrounding_raw(BigFloat, r) do + setrounding_raw(BigFloat, r) do BigFloat(numerator(x))::BigFloat / BigFloat(denominator(x), r_den)::BigFloat end end end -function _opposite_round(r::Base.MPFR.MPFRRoundingMode) - r == MPFR.MPFRRoundUp && return MPFR.MPFRRoundDown - r == MPFR.MPFRRoundDown && return MPFR.MPFRRoundUp +function _opposite_round(r::MPFR.MPFRRoundingMode) + r == MPFRRoundUp && return MPFRRoundDown + r == MPFRRoundDown && return MPFRRoundUp return r end From 3be9e739218fcaa8414a8efeea4bb5036e0d5166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Tue, 22 Jul 2025 21:34:49 +0200 Subject: [PATCH 4/6] Minor cleanup --- base/mpfr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index cc2ed02df6b84..cb51d21aa5bc5 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -399,7 +399,7 @@ function BigFloat(x::Rational, r::MPFRRoundingMode=rounding_raw(BigFloat); preci end end end -function _opposite_round(r::MPFR.MPFRRoundingMode) +function _opposite_round(r::MPFRRoundingMode) r == MPFRRoundUp && return MPFRRoundDown r == MPFRRoundDown && return MPFRRoundUp return r From e6e98dfe2a7b238fc35a70c0d276c0c7d240d213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Thu, 24 Jul 2025 18:15:15 +0200 Subject: [PATCH 5/6] Add tests --- test/mpfr.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/mpfr.jl b/test/mpfr.jl index 8a537d1d4acd8..922ada0131f9b 100644 --- a/test/mpfr.jl +++ b/test/mpfr.jl @@ -35,6 +35,9 @@ import Base.MPFR @test typeof(BigFloat(1//1)) == BigFloat @test typeof(BigFloat(one(Rational{BigInt}))) == BigFloat + rat = 1 // (big(2)^300 + 1) + @test BigFloat(rat, MPFRRoundDown) < rat < BigFloat(rat, MPFRRoundUp) + @test BigFloat(-rat, RoundUp) < -rat < BigFloat(-rat, RoundDown) # BigFloat constructor respects global precision when not specified let prec = precision(BigFloat) < 16 ? 256 : precision(BigFloat) รท 2 From d98ad9865fd016132c30fa1d8501d7111cc47c74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Fri, 25 Jul 2025 17:11:07 +0200 Subject: [PATCH 6/6] Fix typo --- test/mpfr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/mpfr.jl b/test/mpfr.jl index 922ada0131f9b..48477fc4dbcb7 100644 --- a/test/mpfr.jl +++ b/test/mpfr.jl @@ -36,7 +36,7 @@ import Base.MPFR @test typeof(BigFloat(1//1)) == BigFloat @test typeof(BigFloat(one(Rational{BigInt}))) == BigFloat rat = 1 // (big(2)^300 + 1) - @test BigFloat(rat, MPFRRoundDown) < rat < BigFloat(rat, MPFRRoundUp) + @test BigFloat(rat, RoundDown) < rat < BigFloat(rat, RoundUp) @test BigFloat(-rat, RoundUp) < -rat < BigFloat(-rat, RoundDown) # BigFloat constructor respects global precision when not specified