Skip to content

Commit

Permalink
Merge pull request #38046 from JuliaLang/jb/spj/fixbigfloat
Browse files Browse the repository at this point in the history
Fix some bugs with printf and BigFloat
  • Loading branch information
quinnj authored Oct 16, 2020
2 parents 47d6067 + 91bafdf commit 1dd89ec
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 6 deletions.
30 changes: 24 additions & 6 deletions stdlib/Printf/src/Printf.jl
Original file line number Diff line number Diff line change
Expand Up @@ -379,16 +379,34 @@ tofloat(x) = Float64(x)
tofloat(x::Base.IEEEFloat) = x
tofloat(x::BigFloat) = x

_snprintf(ptr, siz, str, arg) =
@ccall "libmpfr".mpfr_snprintf(ptr::Ptr{UInt8}, siz::Csize_t, str::Ptr{UInt8};
arg::Ref{BigFloat})::Cint

const __BIG_FLOAT_MAX__ = 8192

@inline function fmt(buf, pos, arg, spec::Spec{T}) where {T <: Floats}
leftalign, plus, space, zero, hash, width, prec =
spec.leftalign, spec.plus, spec.space, spec.zero, spec.hash, spec.width, spec.precision
x = tofloat(arg)
if x isa BigFloat && isfinite(x)
ptr = pointer(buf, pos)
newpos = @ccall "libmpfr".mpfr_snprintf(ptr::Ptr{UInt8}, (length(buf) - pos + 1)::Csize_t, string(spec; modifier="R")::Ptr{UInt8}; arg::Ref{BigFloat})::Cint
newpos > 0 || error("invalid printf formatting for BigFloat")
return pos + newpos
elseif x isa BigFloat
if x isa BigFloat
if isfinite(x)
GC.@preserve buf begin
siz = length(buf) - pos + 1
str = string(spec; modifier="R")
len = _snprintf(pointer(buf, pos), siz, str, x)
if len > siz
maxout = max(__BIG_FLOAT_MAX__,
ceil(Int, precision(x) * log(2) / log(10)) + 25)
len > maxout &&
error("Over $maxout bytes $len needed to output BigFloat $x")
resize!(buf, len + 1)
len = _snprintf(pointer(buf, pos), len + 1, str, x)
end
len > 0 || throw(ArgumentError("invalid printf formatting $str for BigFloat"))
return pos + len
end
end
x = Float64(x)
end
if T == Val{'e'} || T == Val{'E'}
Expand Down
7 changes: 7 additions & 0 deletions stdlib/Printf/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,13 @@ end
# Check bug with trailing nul printing BigFloat
@test (Printf.@sprintf("%.330f", BigFloat(1)))[end] != '\0'

# Check bugs with truncated output printing BigFloat
@test (Printf.@sprintf("%f", parse(BigFloat, "1e400"))) ==
"10000000000000000000000000000000000000000000000000000000000000000000000000000025262527574416492004687051900140830217136998040684679611623086405387447100385714565637522507383770691831689647535911648520404034824470543643098638520633064715221151920028135130764414460468236314621044034960475540018328999334468948008954289495190631358190153259681118693204411689043999084305348398480210026863210192871358464.000000"

# Check that does not attempt to output incredibly large amounts of digits
@test_throws ErrorException Printf.@sprintf("%f", parse(BigFloat, "1e99999"))

# issue #29662
@test (Printf.@sprintf "%12.3e" pi*1e100) == " 3.142e+100"

Expand Down

0 comments on commit 1dd89ec

Please sign in to comment.