Skip to content

Commit 9c4c882

Browse files
RalphASsimonbyrne
authored andcommitted
methods needed for [s]printf macros (#24)
* implement printf functionality Code copied from Base versions for BigFloat * accommodate < v1.1 digits usage
1 parent 4c2aa17 commit 9c4c882

File tree

5 files changed

+105
-2
lines changed

5 files changed

+105
-2
lines changed

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Requires = "ae029012-a4dd-5104-9daa-d747884805df"
77
[extras]
88
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
99
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
10+
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
1011

1112
[targets]
12-
test = ["Test", "SpecialFunctions"]
13-
13+
test = ["Test", "SpecialFunctions", "Printf"]

src/Quadmath.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,4 +558,6 @@ end
558558
print(io::IO, b::Float128) = print(io, string(b))
559559
show(io::IO, b::Float128) = print(io, string(b))
560560

561+
include("printf.jl")
562+
561563
end # module Quadmath

src/printf.jl

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import Base.Printf: ini_dec, fix_dec, ini_hex, ini_HEX
2+
3+
if VERSION < v"1.1"
4+
using Base.Grisu: DIGITSs
5+
fix_dec(out, d::Float128, flags::String, width::Int, precision::Int, c::Char) = fp128_printf(out, d, flags, width, precision, c, DIGITSs[Threads.threadid()])
6+
ini_dec(out, d::Float128, ndigits::Int, flags::String, width::Int, precision::Int, c::Char) = fp128_printf(out, d, flags, width, precision, c, DIGITSs[Threads.threadid()])
7+
ini_hex(out, d::Float128, ndigits::Int, flags::String, width::Int, precision::Int, c::Char) = fp128_printf(out, d, flags, width, precision, c, DIGITSs[Threads.threadid()])
8+
ini_HEX(out, d::Float128, ndigits::Int, flags::String, width::Int, precision::Int, c::Char) = fp128_printf(out, d, flags, width, precision, c, DIGITSs[Threads.threadid()])
9+
ini_hex(out, d::Float128, flags::String, width::Int, precision::Int, c::Char) = fp128_printf(out, d, flags, width, precision, c, DIGITSs[Threads.threadid()])
10+
ini_HEX(out, d::Float128, flags::String, width::Int, precision::Int, c::Char) = fp128_printf(out, d, flags, width, precision, c, DIGITSs[Threads.threadid()])
11+
else
12+
fix_dec(out, d::Float128, flags::String, width::Int, precision::Int, c::Char, digits) = fp128_printf(out, d, flags, width, precision, c, digits)
13+
ini_dec(out, d::Float128, ndigits::Int, flags::String, width::Int, precision::Int, c::Char, digits) = fp128_printf(out, d, flags, width, precision, c, digits)
14+
ini_hex(out, d::Float128, ndigits::Int, flags::String, width::Int, precision::Int, c::Char, digits) = fp128_printf(out, d, flags, width, precision, c, digits)
15+
ini_HEX(out, d::Float128, ndigits::Int, flags::String, width::Int, precision::Int, c::Char, digits) = fp128_printf(out, d, flags, width, precision, c, digits)
16+
ini_hex(out, d::Float128, flags::String, width::Int, precision::Int, c::Char, digits) = fp128_printf(out, d, flags, width, precision, c, digits)
17+
ini_HEX(out, d::Float128, flags::String, width::Int, precision::Int, c::Char, digits) = fp128_printf(out, d, flags, width, precision, c, digits)
18+
end
19+
20+
function fp128_printf(out, d::Float128, flags::String, width::Int, precision::Int, c::Char, digits)
21+
fmt_len = sizeof(flags)+4
22+
if width > 0
23+
fmt_len += ndigits(width)
24+
end
25+
if precision >= 0
26+
fmt_len += ndigits(precision)+1
27+
end
28+
fmt = IOBuffer(maxsize=fmt_len)
29+
print(fmt, '%')
30+
print(fmt, flags)
31+
if width > 0
32+
print(fmt, width)
33+
end
34+
if precision == 0
35+
print(fmt, '.')
36+
print(fmt, '0')
37+
elseif precision > 0
38+
print(fmt, '.')
39+
print(fmt, precision)
40+
end
41+
print(fmt, 'Q')
42+
print(fmt, c)
43+
write(fmt, UInt8(0))
44+
printf_fmt = take!(fmt)
45+
@assert length(printf_fmt) == fmt_len
46+
bufsiz = length(digits)
47+
lng = @ccall(libquadmath.quadmath_snprintf(digits::Ptr{UInt8}, bufsiz::Csize_t, printf_fmt::Ptr{UInt8}, d::(Cfloat128...))::Cint)
48+
lng > 0 || error("invalid printf formatting for Float128")
49+
unsafe_write(out, pointer(digits), min(lng, bufsiz-1))
50+
return (false, ())
51+
end

test/printf.jl

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using Printf
2+
3+
@testset "printf" begin
4+
for (fmt, val) in (("%7.2f", " 1.23"),
5+
("%-7.2f", "1.23 "),
6+
("%07.2f", "0001.23"),
7+
("%.0f", "1"),
8+
("%#.0f", "1."),
9+
("%.4e", "1.2345e+00"),
10+
("%.4E", "1.2345E+00"),
11+
("%.2a", "0x1.3cp+0"),
12+
("%.2A", "0X1.3CP+0")),
13+
num in (Float128(1.2345),)
14+
@test @eval(@sprintf($fmt, $num) == $val)
15+
end
16+
@test (@sprintf "%f" Float128(Inf)) == "Inf"
17+
@test (@sprintf "%f" Float128(NaN)) == "NaN"
18+
@test (@sprintf "%.0e" Float128(3e142)) == "3e+142"
19+
@test (@sprintf "%#.0e" Float128(3e142)) == "3.e+142"
20+
21+
@test (@sprintf "%.0e" Float128(big"3e1042")) == "3e+1042"
22+
23+
for (val, res) in ((Float128(12345678.), "1.23457e+07"),
24+
(Float128(1234567.8), "1.23457e+06"),
25+
(Float128(123456.78), "123457"),
26+
(Float128(12345.678), "12345.7"))
27+
@test (@sprintf("%.6g", val) == res)
28+
end
29+
30+
for (fmt, val) in (("%10.5g", " 123.4"),
31+
("%+10.5g", " +123.4"),
32+
("% 10.5g"," 123.4"),
33+
("%#10.5g", " 123.40"),
34+
("%-10.5g", "123.4 "),
35+
("%-+10.5g", "+123.4 "),
36+
("%010.5g", "00000123.4")),
37+
num in (Float128(123.4),)
38+
@test @eval(@sprintf($fmt, $num) == $val)
39+
end
40+
@test( @sprintf( "%10.5g", Float128(-123.4) ) == " -123.4")
41+
@test( @sprintf( "%010.5g", Float128(-123.4) ) == "-0000123.4")
42+
@test( @sprintf( "%.6g", Float128(12340000.0) ) == "1.234e+07")
43+
@test( @sprintf( "%#.6g", Float128(12340000.0)) == "1.23400e+07")
44+
45+
@test (@sprintf "%a" Float128(1.5)) == "0x1.8p+0"
46+
47+
end
48+

test/runtests.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,5 @@ end
109109
end
110110

111111
include("specfun.jl")
112+
113+
include("printf.jl")

0 commit comments

Comments
 (0)