From 59f64e9041506ddecb00e7162512145975449560 Mon Sep 17 00:00:00 2001 From: John M Kuhn Date: Wed, 14 Feb 2018 13:23:58 -0500 Subject: [PATCH 1/2] Reimplement show --- REQUIRE | 2 +- src/DecFP.jl | 85 +++++++++++++++++++++++++++++++++++++++++++----- test/runtests.jl | 20 ++++++++++++ 3 files changed, 98 insertions(+), 9 deletions(-) diff --git a/REQUIRE b/REQUIRE index 2573b15..5ddb4fa 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,3 +1,3 @@ julia 0.6 -Compat 0.46.0 +Compat 0.53.0 BinDeps diff --git a/src/DecFP.jl b/src/DecFP.jl index cbb22d6..ea0cd50 100644 --- a/src/DecFP.jl +++ b/src/DecFP.jl @@ -71,14 +71,6 @@ function isnanstr(s::AbstractString) return true end -function Base.show(io::IO, x::DecimalFloatingPoint) - s = @sprintf("%g", x) - if contains(s, r"^-?\d+$") - s *= ".0" - end - print(io, s) -end - for w in (32,64,128) BID = Symbol(string("Dec",w)) Ti = eval(Symbol(string("UInt",w))) @@ -105,6 +97,83 @@ for w in (32,64,128) $BID(x::AbstractString) = parse($BID, x) + function Base.show(io::IO, x::$BID) + if isnan(x) + write(io, "NaN") + return + end + if isinf(x) + if signbit(x) + write(io, "-Inf") + else + write(io, "Inf") + end + return + end + if x == 0 + if signbit(x) + write(io, "-0.0") + else + write(io, "0.0") + end + return + end + ccall(($(bidsym(w,"to_string")), libbid), Cvoid, (Ptr{UInt8}, $BID), _buffer, x) + if _buffer[1] == UInt8('-') + write(io, '-') + end + normalized_exponent = nox(ccall(($(bidsym(w,"ilogb")), libbid), Cint, ($BID,), x)) + lastdigitindex = Compat.findfirst(equalto(UInt8('E')), _buffer) - 1 + lastnonzeroindex = Compat.findlast(!equalto(UInt8('0')), view(_buffer, 1:lastdigitindex)) + if -5 < normalized_exponent < 6 + # %f + if normalized_exponent >= 0 + if normalized_exponent > lastnonzeroindex - 2 + unsafe_write(io, pointer(_buffer, 2), lastnonzeroindex - 1) + write(io, '0'^(normalized_exponent - lastnonzeroindex + 2), ".0") + elseif normalized_exponent == lastnonzeroindex - 2 + unsafe_write(io, pointer(_buffer, 2), lastnonzeroindex - 1) + write(io, ".0") + else + unsafe_write(io, pointer(_buffer, 2), normalized_exponent + 1) + write(io, '.') + unsafe_write(io, pointer(_buffer, normalized_exponent + 3), lastnonzeroindex - normalized_exponent - 2) + end + else + if normalized_exponent == -1 + write(io, "0.") + else + write(io, "0.", '0'^(-normalized_exponent - 1)) + end + unsafe_write(io, pointer(_buffer, 2), lastnonzeroindex - 1) + end + else + # %e + write(io, _buffer[2], '.') + if lastnonzeroindex == 2 + write(io, '0') + else + unsafe_write(io, pointer(_buffer, 3), lastnonzeroindex - 2) + end + write(io, 'e') + if normalized_exponent < 0 + write(io, '-') + normalized_exponent = -normalized_exponent + end + b_lb = div(normalized_exponent, 10) + b = 1 + while b <= b_lb + b *= 10 + end + r = normalized_exponent + while b > 0 + q, r = divrem(r, b) + write(io, Char('0' + q)) + b = div(b, 10) + end + end + end + function Base.Printf.fix_dec(x::$BID, n::Int) if n > length(DIGITS) - 1 n = length(DIGITS) - 1 diff --git a/test/runtests.jl b/test/runtests.jl index e580fc6..a99c73d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -42,6 +42,26 @@ for T in (Dec32, Dec64, Dec128) @test parse(T, "0.1")::T == T(1//10) @test T("0.1")::T == T(1//10) + io = IOBuffer() + show(io, T("NaN")); @test String(take!(io)) == "NaN" + show(io, T("Inf")); @test String(take!(io)) == "Inf" + show(io, T("-Inf")); @test String(take!(io)) == "-Inf" + show(io, T("0")); @test String(take!(io)) == "0.0" + show(io, T("-0")); @test String(take!(io)) == "-0.0" + show(io, T("1")); @test String(take!(io)) == "1.0" + show(io, T("-1")); @test String(take!(io)) == "-1.0" + show(io, T("1.000")); @test String(take!(io)) == "1.0" + show(io, T("1.000")); @test String(take!(io)) == "1.0" + show(io, T("1e5")); @test String(take!(io)) == "100000.0" + show(io, T("1e6")); @test String(take!(io)) == "1.0e6" + show(io, T("1.23456e6")); @test String(take!(io)) == "1.23456e6" + show(io, T("1e-1")); @test String(take!(io)) == "0.1" + show(io, T("1e-4")); @test String(take!(io)) == "0.0001" + show(io, T("1e-5")); @test String(take!(io)) == "1.0e-5" + show(io, T("1.20e3")); @test String(take!(io)) == "1200.0" + show(io, T("123.456")); @test String(take!(io)) == "123.456" + show(io, T("0.00123456")); @test String(take!(io)) == "0.00123456" + # some Dec128 tests fail due to Issue #47 if T != Dec128 @test @sprintf("%7.2f", T("1.2345")) == " 1.23" From d12a43ccbd5925e4550a6b6236a9131218dd6352 Mon Sep 17 00:00:00 2001 From: John M Kuhn Date: Fri, 16 Feb 2018 10:50:09 -0500 Subject: [PATCH 2/2] Review updates --- src/DecFP.jl | 72 +++++++++++++++++++++++++----------------------- test/runtests.jl | 1 - 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/DecFP.jl b/src/DecFP.jl index ea0cd50..7628dd6 100644 --- a/src/DecFP.jl +++ b/src/DecFP.jl @@ -3,6 +3,23 @@ module DecFP using Compat, Compat.Printf, Compat.Unicode +# When Compat PR #491 is merged, REQUIRE that version and delete this +# 0.7.0-DEV.3469 +@static if !isdefined(Base, :GC) + @eval module GC + using Base: gc + const enable = Base.gc_enable + @static if !isdefined(Base, Symbol("@gc_preserve")) + macro preserve(args...) + esc(args[end]) + end + else + @eval const $(Symbol("@preserve")) = Base.$(Symbol("@gc_preserve")) + end + end + export GC +end + export Dec32, Dec64, Dec128, @d_str, @d32_str, @d64_str, @d128_str const libbid = joinpath(dirname(@__FILE__), "..", "deps", "libbid$(Sys.WORD_SIZE)") @@ -98,26 +115,9 @@ for w in (32,64,128) $BID(x::AbstractString) = parse($BID, x) function Base.show(io::IO, x::$BID) - if isnan(x) - write(io, "NaN") - return - end - if isinf(x) - if signbit(x) - write(io, "-Inf") - else - write(io, "Inf") - end - return - end - if x == 0 - if signbit(x) - write(io, "-0.0") - else - write(io, "0.0") - end - return - end + isnan(x) && (write(io, "NaN"); return) + isinf(x) && (write(io, signbit(x) ? "-Inf" : "Inf"); return) + x == 0 && (write(io, signbit(x) ? "-0.0" : "0.0"); return) ccall(($(bidsym(w,"to_string")), libbid), Cvoid, (Ptr{UInt8}, $BID), _buffer, x) if _buffer[1] == UInt8('-') write(io, '-') @@ -128,24 +128,19 @@ for w in (32,64,128) if -5 < normalized_exponent < 6 # %f if normalized_exponent >= 0 - if normalized_exponent > lastnonzeroindex - 2 - unsafe_write(io, pointer(_buffer, 2), lastnonzeroindex - 1) - write(io, '0'^(normalized_exponent - lastnonzeroindex + 2), ".0") - elseif normalized_exponent == lastnonzeroindex - 2 - unsafe_write(io, pointer(_buffer, 2), lastnonzeroindex - 1) + if normalized_exponent >= lastnonzeroindex - 2 + GC.@preserve _buffer unsafe_write(io, pointer(_buffer, 2), lastnonzeroindex - 1) + writezeros(io, normalized_exponent - lastnonzeroindex + 2) write(io, ".0") else - unsafe_write(io, pointer(_buffer, 2), normalized_exponent + 1) + GC.@preserve _buffer unsafe_write(io, pointer(_buffer, 2), normalized_exponent + 1) write(io, '.') - unsafe_write(io, pointer(_buffer, normalized_exponent + 3), lastnonzeroindex - normalized_exponent - 2) + GC.@preserve _buffer unsafe_write(io, pointer(_buffer, normalized_exponent + 3), lastnonzeroindex - normalized_exponent - 2) end else - if normalized_exponent == -1 - write(io, "0.") - else - write(io, "0.", '0'^(-normalized_exponent - 1)) - end - unsafe_write(io, pointer(_buffer, 2), lastnonzeroindex - 1) + write(io, "0.") + writezeros(io, -normalized_exponent - 1) + GC.@preserve _buffer unsafe_write(io, pointer(_buffer, 2), lastnonzeroindex - 1) end else # %e @@ -153,7 +148,7 @@ for w in (32,64,128) if lastnonzeroindex == 2 write(io, '0') else - unsafe_write(io, pointer(_buffer, 3), lastnonzeroindex - 2) + GC.@preserve _buffer unsafe_write(io, pointer(_buffer, 3), lastnonzeroindex - 2) end write(io, 'e') if normalized_exponent < 0 @@ -168,10 +163,11 @@ for w in (32,64,128) r = normalized_exponent while b > 0 q, r = divrem(r, b) - write(io, Char('0' + q)) + write(io, UInt8('0') + (q%UInt8)) b = div(b, 10) end end + return end function Base.Printf.fix_dec(x::$BID, n::Int) @@ -438,4 +434,10 @@ function xchk(x, exc::Type{E}, args...; mask::Integer=0x3f) where {E<:Exception} return x end +function writezeros(io::IO, n::Int) + for i = 1:n + write(io, UInt8('0')) + end +end + end # module diff --git a/test/runtests.jl b/test/runtests.jl index a99c73d..a54f5d1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -51,7 +51,6 @@ for T in (Dec32, Dec64, Dec128) show(io, T("1")); @test String(take!(io)) == "1.0" show(io, T("-1")); @test String(take!(io)) == "-1.0" show(io, T("1.000")); @test String(take!(io)) == "1.0" - show(io, T("1.000")); @test String(take!(io)) == "1.0" show(io, T("1e5")); @test String(take!(io)) == "100000.0" show(io, T("1e6")); @test String(take!(io)) == "1.0e6" show(io, T("1.23456e6")); @test String(take!(io)) == "1.23456e6"