Skip to content

Commit 5462da6

Browse files
jmkuhnstevengj
authored andcommitted
Fix printf formatting
1 parent 14aa05d commit 5462da6

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

src/DecFP.jl

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const libbid = joinpath(dirname(@__FILE__), "..", "deps", "libbid$(Sys.WORD_SIZE
66
const _buffer = Vector{UInt8}(1024)
77

88
import Base.promote_rule
9+
import Base.Grisu.DIGITS
910

1011
# https://github.com/JuliaLang/julia/pull/20005
1112
if VERSION < v"0.7.0-DEV.896"
@@ -102,11 +103,80 @@ for w in (32,64,128)
102103
return xchk(x, InexactError, :parse, $BID, s)
103104
end
104105

106+
$BID(x::AbstractString) = parse($BID, x)
107+
105108
function Base.show(io::IO, x::$BID)
106109
ccall(($(bidsym(w,"to_string")), libbid), Void, (Ptr{UInt8}, $BID), _buffer, x)
107110
unsafe_write(io, pointer(_buffer), ccall(:strlen, Csize_t, (Ptr{UInt8},), _buffer))
108111
end
109112

113+
function Base.Printf.fix_dec(x::$BID, n::Int)
114+
if n > length(DIGITS) - 1
115+
n = length(DIGITS) - 1
116+
end
117+
# rounded = round(x * exp10($BID(n)), RoundNearestTiesAway)
118+
rounded = xchk(ccall(($(bidsym(w,"round_integral_nearest_away")), libbid), $BID, ($BID,), x * exp10($BID(n))), InexactError, :round, $BID, x, mask=INVALID | OVERFLOW)
119+
if rounded == 0
120+
DIGITS[1] = UInt8('0')
121+
return Int32(1), Int32(1), signbit(x)
122+
end
123+
ccall(($(bidsym(w,"to_string")), libbid), Void, (Ptr{UInt8}, $BID), _buffer, rounded)
124+
trailing_zeros = 0
125+
i = 2
126+
while _buffer[i] != UInt8('E')
127+
DIGITS[i - 1] = _buffer[i]
128+
if _buffer[i] == UInt8('0')
129+
trailing_zeros += 1
130+
else
131+
trailing_zeros = 0
132+
end
133+
i += 1
134+
end
135+
ndigits = i - 2
136+
len = ndigits - trailing_zeros
137+
i += 1
138+
if _buffer[i] == UInt8('+')
139+
expsign = +1
140+
elseif _buffer[i] == UInt8('-')
141+
expsign = -1
142+
end
143+
exponent = 0
144+
i += 1
145+
while _buffer[i] != 0x00
146+
exponent = exponent * 10 + _buffer[i] - UInt8('0')
147+
i += 1
148+
end
149+
exponent *= expsign
150+
pt = ndigits + exponent - n
151+
neg = signbit(x)
152+
return Int32(len), Int32(pt), neg
153+
end
154+
155+
function Base.Printf.ini_dec(x::$BID, n::Int)
156+
if n > length(DIGITS) - 1
157+
n = length(DIGITS) - 1
158+
end
159+
if x == 0
160+
for i = 1:n
161+
DIGITS[i] = UInt8('0')
162+
end
163+
return Int32(1), Int32(1), signbit(x)
164+
end
165+
normalized_exponent = nox(ccall(($(bidsym(w,"ilogb")), libbid), Cint, ($BID,), x))
166+
# rounded = round(x * exp10($BID(n - 1 - normalized_exponent)), RoundNearestTiesAway)
167+
rounded = xchk(ccall(($(bidsym(w,"round_integral_nearest_away")), libbid), $BID, ($BID,), x * exp10($BID(n - 1 - normalized_exponent))), InexactError, :round, $BID, x, mask=INVALID | OVERFLOW)
168+
rounded_exponent = nox(ccall(($(bidsym(w,"ilogb")), libbid), Cint, ($BID,), rounded))
169+
ccall(($(bidsym(w,"to_string")), libbid), Void, (Ptr{UInt8}, $BID), _buffer, rounded)
170+
i = 2
171+
while _buffer[i] != UInt8('E')
172+
DIGITS[i - 1] = _buffer[i]
173+
i += 1
174+
end
175+
pt = normalized_exponent + rounded_exponent - n + 2
176+
neg = signbit(x)
177+
return Int32(n), Int32(pt), neg
178+
end
179+
110180
Base.fma(x::$BID, y::$BID, z::$BID) = nox(ccall(($(bidsym(w,"fma")), libbid), $BID, ($BID,$BID,$BID), x, y, z))
111181
Base.muladd(x::$BID, y::$BID, z::$BID) = fma(x,y,z) # faster than x+y*z
112182

test/runtests.jl

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,52 @@ for T in (Dec32, Dec64, Dec128)
3737
@test parse(T,"-inf")::T == typemin(T)::T
3838

3939
@test parse(T, "0.1")::T == T(1//10)
40+
@test T("0.1")::T == T(1//10)
41+
42+
# some Dec128 tests fail due to Issue #47
43+
if T != Dec128
44+
@test @sprintf("%7.2f", T("1.2345")) == " 1.23"
45+
@test @sprintf("%-7.2f", T("1.2345")) == "1.23 "
46+
@test @sprintf("%07.2f", T("1.2345")) == "0001.23"
47+
@test @sprintf("%.0f", T("1.2345")) == "1"
48+
@test @sprintf("%#.0f", T("1.2345")) == "1."
49+
@test @sprintf("%.4e", T("1.2345")) == "1.2345e+00"
50+
@test @sprintf("%.4E", T("1.2345")) == "1.2345E+00"
51+
52+
@test @sprintf("%6.2f", T("9.999")) == " 10.00"
53+
@test @sprintf("%9.2e", T("9.999e5")) == " 1.00e+06"
54+
55+
@test @sprintf("%f", T("Inf")) == "Inf"
56+
@test @sprintf("%f", T("NaN")) == "NaN"
57+
58+
@test @sprintf("%.0e", T("3e42")) == "3e+42"
59+
@test @sprintf("%#.0e", T("3e42")) == "3.e+42"
60+
61+
@test @sprintf("%e", T("3e42")) == "3.000000e+42"
62+
@test @sprintf("%E", T("3e42")) == "3.000000E+42"
63+
@test @sprintf("%e", T("3e-42")) == "3.000000e-42"
64+
@test @sprintf("%E", T("3e-42")) == "3.000000E-42"
65+
66+
@sprintf("%.6g", T("12345670.")) == "1.23457e+07"
67+
@sprintf("%.6g", T("1234567.")) == "1.23457e+06"
68+
@sprintf("%.6g", T("123456.7")) == "123457"
69+
@sprintf("%.6g", T("12345.67")) == "12345.7"
70+
@sprintf("%.6g", T("12340000.0")) == "1.234e+07"
71+
72+
@test @sprintf("%10.5g", T("123.4")) == " 123.4"
73+
@test @sprintf("%+10.5g", T("123.4")) == " +123.4"
74+
@test @sprintf("% 10.5g", T("123.4")) == " 123.4"
75+
@test @sprintf("%#10.5g", T("123.4")) == " 123.40"
76+
@test @sprintf("%-10.5g", T("123.4")) == "123.4 "
77+
@test @sprintf("%-+10.5g", T("123.4")) == "+123.4 "
78+
@test @sprintf("%010.5g", T("123.4")) == "00000123.4"
79+
@test @sprintf("%10.5g", T("-123.4")) == " -123.4"
80+
@test @sprintf("%010.5g", T("-123.4")) == "-0000123.4"
81+
@test @sprintf("%.6g", T("12340000.0")) == "1.234e+07"
82+
@test @sprintf("%#.6g", T("12340000.0")) == "1.23400e+07"
83+
84+
@test @sprintf("%.2f %.4f", T("12.34567"), 9.87) == "12.35 9.8700"
85+
end
4086

4187
x,y,z = 1.5, -3.25, 0.0625 # exactly represented in binary
4288
xd = T(x); yd = T(y); zd = T(z)

0 commit comments

Comments
 (0)