Skip to content

Commit 135efec

Browse files
jmkuhnstevengj
authored andcommitted
Reimplement show (#60)
* Reimplement show * Review updates
1 parent 491d2e4 commit 135efec

File tree

3 files changed

+99
-9
lines changed

3 files changed

+99
-9
lines changed

REQUIRE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
julia 0.6
2-
Compat 0.46.0
2+
Compat 0.53.0
33
BinDeps

src/DecFP.jl

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,23 @@ module DecFP
33

44
using Compat, Compat.Printf, Compat.Unicode
55

6+
# When Compat PR #491 is merged, REQUIRE that version and delete this
7+
# 0.7.0-DEV.3469
8+
@static if !isdefined(Base, :GC)
9+
@eval module GC
10+
using Base: gc
11+
const enable = Base.gc_enable
12+
@static if !isdefined(Base, Symbol("@gc_preserve"))
13+
macro preserve(args...)
14+
esc(args[end])
15+
end
16+
else
17+
@eval const $(Symbol("@preserve")) = Base.$(Symbol("@gc_preserve"))
18+
end
19+
end
20+
export GC
21+
end
22+
623
export Dec32, Dec64, Dec128, @d_str, @d32_str, @d64_str, @d128_str
724

825
const libbid = joinpath(dirname(@__FILE__), "..", "deps", "libbid$(Sys.WORD_SIZE)")
@@ -71,14 +88,6 @@ function isnanstr(s::AbstractString)
7188
return true
7289
end
7390

74-
function Base.show(io::IO, x::DecimalFloatingPoint)
75-
s = @sprintf("%g", x)
76-
if contains(s, r"^-?\d+$")
77-
s *= ".0"
78-
end
79-
print(io, s)
80-
end
81-
8291
for w in (32,64,128)
8392
BID = Symbol(string("Dec",w))
8493
Ti = eval(Symbol(string("UInt",w)))
@@ -105,6 +114,62 @@ for w in (32,64,128)
105114

106115
$BID(x::AbstractString) = parse($BID, x)
107116

117+
function Base.show(io::IO, x::$BID)
118+
isnan(x) && (write(io, "NaN"); return)
119+
isinf(x) && (write(io, signbit(x) ? "-Inf" : "Inf"); return)
120+
x == 0 && (write(io, signbit(x) ? "-0.0" : "0.0"); return)
121+
ccall(($(bidsym(w,"to_string")), libbid), Cvoid, (Ptr{UInt8}, $BID), _buffer, x)
122+
if _buffer[1] == UInt8('-')
123+
write(io, '-')
124+
end
125+
normalized_exponent = nox(ccall(($(bidsym(w,"ilogb")), libbid), Cint, ($BID,), x))
126+
lastdigitindex = Compat.findfirst(equalto(UInt8('E')), _buffer) - 1
127+
lastnonzeroindex = Compat.findlast(!equalto(UInt8('0')), view(_buffer, 1:lastdigitindex))
128+
if -5 < normalized_exponent < 6
129+
# %f
130+
if normalized_exponent >= 0
131+
if normalized_exponent >= lastnonzeroindex - 2
132+
GC.@preserve _buffer unsafe_write(io, pointer(_buffer, 2), lastnonzeroindex - 1)
133+
writezeros(io, normalized_exponent - lastnonzeroindex + 2)
134+
write(io, ".0")
135+
else
136+
GC.@preserve _buffer unsafe_write(io, pointer(_buffer, 2), normalized_exponent + 1)
137+
write(io, '.')
138+
GC.@preserve _buffer unsafe_write(io, pointer(_buffer, normalized_exponent + 3), lastnonzeroindex - normalized_exponent - 2)
139+
end
140+
else
141+
write(io, "0.")
142+
writezeros(io, -normalized_exponent - 1)
143+
GC.@preserve _buffer unsafe_write(io, pointer(_buffer, 2), lastnonzeroindex - 1)
144+
end
145+
else
146+
# %e
147+
write(io, _buffer[2], '.')
148+
if lastnonzeroindex == 2
149+
write(io, '0')
150+
else
151+
GC.@preserve _buffer unsafe_write(io, pointer(_buffer, 3), lastnonzeroindex - 2)
152+
end
153+
write(io, 'e')
154+
if normalized_exponent < 0
155+
write(io, '-')
156+
normalized_exponent = -normalized_exponent
157+
end
158+
b_lb = div(normalized_exponent, 10)
159+
b = 1
160+
while b <= b_lb
161+
b *= 10
162+
end
163+
r = normalized_exponent
164+
while b > 0
165+
q, r = divrem(r, b)
166+
write(io, UInt8('0') + (q%UInt8))
167+
b = div(b, 10)
168+
end
169+
end
170+
return
171+
end
172+
108173
function Base.Printf.fix_dec(x::$BID, n::Int)
109174
if n > length(DIGITS) - 1
110175
n = length(DIGITS) - 1
@@ -369,4 +434,10 @@ function xchk(x, exc::Type{E}, args...; mask::Integer=0x3f) where {E<:Exception}
369434
return x
370435
end
371436

437+
function writezeros(io::IO, n::Int)
438+
for i = 1:n
439+
write(io, UInt8('0'))
440+
end
441+
end
442+
372443
end # module

test/runtests.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,25 @@ for T in (Dec32, Dec64, Dec128)
4242
@test parse(T, "0.1")::T == T(1//10)
4343
@test T("0.1")::T == T(1//10)
4444

45+
io = IOBuffer()
46+
show(io, T("NaN")); @test String(take!(io)) == "NaN"
47+
show(io, T("Inf")); @test String(take!(io)) == "Inf"
48+
show(io, T("-Inf")); @test String(take!(io)) == "-Inf"
49+
show(io, T("0")); @test String(take!(io)) == "0.0"
50+
show(io, T("-0")); @test String(take!(io)) == "-0.0"
51+
show(io, T("1")); @test String(take!(io)) == "1.0"
52+
show(io, T("-1")); @test String(take!(io)) == "-1.0"
53+
show(io, T("1.000")); @test String(take!(io)) == "1.0"
54+
show(io, T("1e5")); @test String(take!(io)) == "100000.0"
55+
show(io, T("1e6")); @test String(take!(io)) == "1.0e6"
56+
show(io, T("1.23456e6")); @test String(take!(io)) == "1.23456e6"
57+
show(io, T("1e-1")); @test String(take!(io)) == "0.1"
58+
show(io, T("1e-4")); @test String(take!(io)) == "0.0001"
59+
show(io, T("1e-5")); @test String(take!(io)) == "1.0e-5"
60+
show(io, T("1.20e3")); @test String(take!(io)) == "1200.0"
61+
show(io, T("123.456")); @test String(take!(io)) == "123.456"
62+
show(io, T("0.00123456")); @test String(take!(io)) == "0.00123456"
63+
4564
# some Dec128 tests fail due to Issue #47
4665
if T != Dec128
4766
@test @sprintf("%7.2f", T("1.2345")) == " 1.23"

0 commit comments

Comments
 (0)