Skip to content

Commit a579446

Browse files
committed
Rework display
1 parent dce5add commit a579446

File tree

4 files changed

+67
-71
lines changed

4 files changed

+67
-71
lines changed

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ version = "0.22.30"
77
CRlibm = "96374032-68de-5a5b-8d9e-752f78720389"
88
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
99
OpenBLASConsistentFPCSR_jll = "6cdc7f73-28fd-5e50-80fb-958a8875b1af"
10+
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
1011
RoundingEmulator = "5eaf0fd0-dfba-4ccb-bf02-d820a40db705"
1112

1213
[weakdeps]
@@ -33,6 +34,7 @@ IntervalSets = "0.7"
3334
LinearAlgebra = "1.10"
3435
MacroTools = "0.5"
3536
OpenBLASConsistentFPCSR_jll = "0.3.29"
37+
Printf = "1.10"
3638
RecipesBase = "1"
3739
RoundingEmulator = "0.2"
3840
SparseArrays = "1.10"

src/IntervalArithmetic.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ include("piecewise.jl")
7777

7878
#
7979

80+
import Printf
81+
8082
include("display.jl")
8183
export setdisplay
8284

src/display.jl

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Display options:
4949
- significant digits: 6
5050
5151
julia> x = interval(0.1, 0.3)
52-
[0.0999999, 0.300001]_com
52+
[0.1, 0.3]_com
5353
5454
julia> setdisplay(:full)
5555
Display options:
@@ -69,7 +69,7 @@ Display options:
6969
- significant digits: 3
7070
7171
julia> x
72-
[0.0999, 0.301]_com
72+
[0.1, 0.3]_com
7373
7474
julia> setdisplay(; decorations = false)
7575
Display options:
@@ -79,7 +79,7 @@ Display options:
7979
- significant digits: 3
8080
8181
julia> x
82-
[0.0999, 0.301]
82+
[0.1, 0.3]
8383
```
8484
"""
8585
function setdisplay(format::Symbol = display_options.format;
@@ -312,41 +312,41 @@ end
312312
# code inspired by `_string(x::BigFloat, k::Integer)` in base/mpfr.jl
313313

314314
function _round_string(x::T, sigdigits::Int, r::RoundingMode) where {T<:AbstractFloat}
315-
str_x = string(x)
316-
str_digits = split(contains(str_x, '.') ? split(str_x, '.'; limit = 2)[2] : str_x, 'e'; limit = 2)[1]
317-
len = length(str_digits)
318-
if isinteger(x) && sigdigits len # `x` is exactly representable
319-
return replace(_round_string(big(x), length(str_x), RoundNearest), "e-0" => "e-")
320-
elseif ispow2(abs(x)) && sigdigits len # `x` is exactly representable
321-
return replace(_round_string(big(x), len + 1, RoundNearest), "e-0" => "e-")
322-
else
323-
return _round_string(big(x), sigdigits, r)
324-
end
325-
end
315+
!isfinite(x) && return string(x)
326316

327-
_round_string(x::BigFloat, sigdigits::Int, ::RoundingMode{:Nearest}) =
328-
Base.MPFR._string(x, sigdigits-1) # `sigdigits-1` digits after the decimal
317+
ndigits = ceil(Int, precision(x) * log10(T(2)))
318+
sci_str = Printf.@sprintf("%.*e", ndigits, x)
329319

330-
function _round_string(x::BigFloat, sigdigits::Int, r::RoundingMode)
331-
if !isfinite(x)
332-
return string(Float64(x))
333-
else
334-
str_x = string(x)
335-
str_digits = split(split(str_x, '.'; limit = 2)[2], 'e'; limit = 2)[1]
336-
len = length(str_digits)
337-
if isinteger(x) && sigdigits len # `x` is exactly representable
338-
return _round_string(big(x), length(str_x), RoundNearest)
339-
elseif ispow2(abs(x)) && sigdigits len # `x` is exactly representable
340-
return _round_string(big(x), len + 1, RoundNearest)
341-
else
342-
# `sigdigits` digits after the decimal
343-
str = Base.MPFR.string_mpfr(x, "%.$(sigdigits)Re")
344-
rounded_str = _round_string(str, r)
345-
return Base.MPFR._prettify_bigfloat(rounded_str)
320+
if abs(x) < floatmax(T)
321+
ndigits_ = ndigits - 1
322+
sci_str_ = Printf.@sprintf("%.*e", ndigits_, x)
323+
324+
if parse(T, sci_str) == parse(T, sci_str_)
325+
ndigits = ndigits_
326+
sci_str = sci_str_
346327
end
347328
end
329+
330+
mantissa = split(sci_str, 'e')[1]
331+
332+
mantissa_digits = replace(mantissa, "." => "")
333+
334+
significant_digits = length(rstrip(mantissa_digits, '0'))
335+
336+
is_representable = significant_digits sigdigits
337+
338+
# `min(sigdigits-1, ndigits)` ensure we do not exceed the precision of `x`
339+
str = is_representable ? Printf.@sprintf("%.*e", min(sigdigits-1, ndigits), x) : _round_string(Printf.@sprintf("%.*e", sigdigits, x), r)
340+
341+
return Base.MPFR._prettify_bigfloat(str)
348342
end
349343

344+
_round_string(x::AbstractFloat, sigdigits::Int, r::RoundingMode{:Nearest}) =
345+
_round_string(big(x), sigdigits, r)
346+
347+
_round_string(x::BigFloat, sigdigits::Int, ::RoundingMode{:Nearest}) =
348+
Base.MPFR._string(x, sigdigits-1) # `sigdigits-1` digits after the decimal
349+
350350
_round_string(s::String, ::RoundingMode{:Up}) =
351351
startswith(s, '-') ? string('-', _round_string_down(s[2:end])) : _round_string_up(s)
352352

test/interval_tests/display.jl

Lines changed: 31 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,16 @@ setprecision(BigFloat, 256) do
1212

1313
@test sprint(show, MIME("text/plain"), emptyinterval(BareInterval{Float64})) == ""
1414

15-
@test sprint(show, MIME("text/plain"), a) == "[-2.22508e-308, 1.30001]"
16-
@test sprint(show, MIME("text/plain"), large_expo) ==
17-
"[0.0, 1.00001e+123456789]₂₅₆"
15+
@test sprint(show, MIME("text/plain"), a) == "[-2.22508e-308, 1.3]"
16+
@test sprint(show, MIME("text/plain"), large_expo) == "[0.0, 1.0e+123456789]₂₅₆"
1817
end
1918

2019
@testset "20 significant digits" begin
2120
# `decorations` keyword has no impact for `BareInterval`
2221
setdisplay(; sigdigits = 20, decorations = true)
2322

24-
@test sprint(show, MIME("text/plain"), a) == "[-2.2250738585072014e-308, 1.3000000000000000445]"
25-
@test sprint(show, MIME("text/plain"), large_expo) ==
26-
"[0.0, 1.0000000000000000001e+123456789]₂₅₆"
23+
@test sprint(show, MIME("text/plain"), a) == "[-2.2250738585072014e-308, 1.3]"
24+
@test sprint(show, MIME("text/plain"), large_expo) == "[0.0, 1.0e+123456789]₂₅₆"
2725
end
2826
end
2927

@@ -45,9 +43,8 @@ setprecision(BigFloat, 256) do
4543

4644
@test sprint(show, MIME("text/plain"), emptyinterval(BareInterval{Float64})) == ""
4745

48-
@test sprint(show, MIME("text/plain"), a) == "0.65 ± 0.650001"
49-
@test sprint(show, MIME("text/plain"), large_expo) ==
50-
"(5.0e+123456788 ± 5.00001e+123456788)₂₅₆"
46+
@test sprint(show, MIME("text/plain"), a) == "0.65 ± 0.65"
47+
@test sprint(show, MIME("text/plain"), large_expo) == "(5.0e+123456788 ± 5.00001e+123456788)₂₅₆"
5148
end
5249
end
5350

@@ -75,13 +72,12 @@ setprecision(BigFloat, 256) do
7572

7673
@test sprint(show, MIME("text/plain"), a) == "[1.0, 2.0]_com"
7774
@test sprint(show, MIME("text/plain"), a_NG) == "[1.0, 2.0]_com_NG"
78-
@test sprint(show, MIME("text/plain"), b) == "[-2.22508e-308, 1.30001]_com"
79-
@test sprint(show, MIME("text/plain"), b32) == "[-1.1755f-38, 1.30001f0]_com"
80-
@test sprint(show, MIME("text/plain"), b16) == "[Float16(-6.104e-5), Float16(1.29981)]_com"
75+
@test sprint(show, MIME("text/plain"), b) == "[-2.22508e-308, 1.3]_com"
76+
@test sprint(show, MIME("text/plain"), b32) == "[-1.1755f-38, 1.3f0]_com"
77+
@test_broken sprint(show, MIME("text/plain"), b16) == "[Float16(-6.104e-5), Float16(1.3)]_com"
8178
@test sprint(show, MIME("text/plain"), br) == "[-11//10, 13//10]_com"
8279
@test sprint(show, MIME("text/plain"), c) == "[-1.0, ∞)_dac"
83-
@test sprint(show, MIME("text/plain"), large_expo) ==
84-
"[0.0, 1.00001e+123456789]₂₅₆_com"
80+
@test sprint(show, MIME("text/plain"), large_expo) == "[0.0, 1.0e+123456789]₂₅₆_com"
8581
end
8682

8783
@testset "No decorations" begin
@@ -92,13 +88,12 @@ setprecision(BigFloat, 256) do
9288

9389
@test sprint(show, MIME("text/plain"), a) == "[1.0, 2.0]"
9490
@test sprint(show, MIME("text/plain"), a_NG) == "[1.0, 2.0]_NG"
95-
@test sprint(show, MIME("text/plain"), b) == "[-2.22508e-308, 1.30001]"
96-
@test sprint(show, MIME("text/plain"), b32) == "[-1.1755f-38, 1.30001f0]"
97-
@test sprint(show, MIME("text/plain"), b16) == "[Float16(-6.104e-5), Float16(1.29981)]"
91+
@test sprint(show, MIME("text/plain"), b) == "[-2.22508e-308, 1.3]"
92+
@test sprint(show, MIME("text/plain"), b32) == "[-1.1755f-38, 1.3f0]"
93+
@test_broken sprint(show, MIME("text/plain"), b16) == "[Float16(-6.104e-5), Float16(1.3)]"
9894
@test sprint(show, MIME("text/plain"), br) == "[-11//10, 13//10]"
9995
@test sprint(show, MIME("text/plain"), c) == "[-1.0, ∞)"
100-
@test sprint(show, MIME("text/plain"), large_expo) ==
101-
"[0.0, 1.00001e+123456789]₂₅₆"
96+
@test sprint(show, MIME("text/plain"), large_expo) == "[0.0, 1.0e+123456789]₂₅₆"
10297
end
10398
end
10499

@@ -107,13 +102,12 @@ setprecision(BigFloat, 256) do
107102

108103
@test sprint(show, MIME("text/plain"), a) == "[1.0, 2.0]_com"
109104
@test sprint(show, MIME("text/plain"), a_NG) == "[1.0, 2.0]_com_NG"
110-
@test sprint(show, MIME("text/plain"), b) == "[-2.2250738585072014e-308, 1.3000000000000000445]_com"
111-
@test sprint(show, MIME("text/plain"), b32) == "[-1.1754944f-38, 1.2999999523162841797f0]_com"
112-
@test sprint(show, MIME("text/plain"), b16) == "[Float16(-6.104e-5), Float16(1.2998046875000000001)]_com"
105+
@test sprint(show, MIME("text/plain"), b) == "[-2.2250738585072014e-308, 1.3]_com"
106+
@test sprint(show, MIME("text/plain"), b32) == "[-1.1754944f-38, 1.3f0]_com"
107+
@test_broken sprint(show, MIME("text/plain"), b16) == "[Float16(-6.104e-5), Float16(1.3)]_com"
113108
@test sprint(show, MIME("text/plain"), br) == "[-11//10, 13//10]_com"
114109
@test sprint(show, MIME("text/plain"), c) == "[-1.0, ∞)_dac"
115-
@test sprint(show, MIME("text/plain"), large_expo) ==
116-
"[0.0, 1.0000000000000000001e+123456789]₂₅₆_com"
110+
@test sprint(show, MIME("text/plain"), large_expo) == "[0.0, 1.0e+123456789]₂₅₆_com"
117111
end
118112
end
119113

@@ -146,13 +140,12 @@ setprecision(BigFloat, 256) do
146140

147141
@test sprint(show, MIME("text/plain"), a) == "(1.5 ± 0.5)_com"
148142
@test sprint(show, MIME("text/plain"), a_NG) == "(1.5 ± 0.5)_com_NG"
149-
@test sprint(show, MIME("text/plain"), b) == "(0.65 ± 0.650001)_com"
150-
@test sprint(show, MIME("text/plain"), b32) == "(0.65f0 ± 0.650001f0)_com"
151-
@test sprint(show, MIME("text/plain"), b16) == "(Float16(0.649902) ± Float16(0.649903))_com"
143+
@test sprint(show, MIME("text/plain"), b) == "(0.65 ± 0.65)_com"
144+
@test_broken sprint(show, MIME("text/plain"), b32) == "(0.65f0 ± 0.65f0)_com"
145+
@test_broken sprint(show, MIME("text/plain"), b16) == "(Float16(0.649902) ± Float16(0.65))_com"
152146
@test sprint(show, MIME("text/plain"), br) == "(1//10 ± 6//5)_com"
153147
@test sprint(show, MIME("text/plain"), c) == "(1.79769e+308 ± ∞)_dac"
154-
@test sprint(show, MIME("text/plain"), large_expo) ==
155-
"(5.0e+123456788 ± 5.00001e+123456788)₂₅₆_com"
148+
@test sprint(show, MIME("text/plain"), large_expo) == "(5.0e+123456788 ± 5.00001e+123456788)₂₅₆_com"
156149
end
157150

158151
@testset "No decorations" begin
@@ -163,13 +156,12 @@ setprecision(BigFloat, 256) do
163156

164157
@test sprint(show, MIME("text/plain"), a) == "1.5 ± 0.5"
165158
@test sprint(show, MIME("text/plain"), a_NG) == "(1.5 ± 0.5)_NG"
166-
@test sprint(show, MIME("text/plain"), b) == "0.65 ± 0.650001"
167-
@test sprint(show, MIME("text/plain"), b32) == "0.65f0 ± 0.650001f0"
168-
@test sprint(show, MIME("text/plain"), b16) == "Float16(0.649902) ± Float16(0.649903)"
159+
@test sprint(show, MIME("text/plain"), b) == "0.65 ± 0.65"
160+
@test_broken sprint(show, MIME("text/plain"), b32) == "0.65f0 ± 0.65f0"
161+
@test_broken sprint(show, MIME("text/plain"), b16) == "Float16(0.649902) ± Float16(0.65)"
169162
@test sprint(show, MIME("text/plain"), br) == "1//10 ± 6//5"
170163
@test sprint(show, MIME("text/plain"), c) == "1.79769e+308 ± ∞"
171-
@test sprint(show, MIME("text/plain"), large_expo) ==
172-
"(5.0e+123456788 ± 5.00001e+123456788)₂₅₆"
164+
@test sprint(show, MIME("text/plain"), large_expo) == "(5.0e+123456788 ± 5.00001e+123456788)₂₅₆"
173165
end
174166
end
175167
end
@@ -190,15 +182,15 @@ setprecision(BigFloat, 256) do
190182

191183
@test sprint(show, MIME("text/plain"), a) == "[0.0, 2.0]_com + im*[1.0, 1.0]_com"
192184
@test sprint(show, MIME("text/plain"), b) == "[0.0, 2.0]_com - im*[1.0, 1.0]_com"
193-
@test sprint(show, MIME("text/plain"), c) == "[0.0, 1.00001e-70]_com - im*[0.999999e-70, 1.00001e-70]_com"
185+
@test sprint(show, MIME("text/plain"), c) == "[0.0, 1.0e-70]_com - im*[1.0e-70, 1.0e-70]_com"
194186
end
195187

196188
@testset "No decorations" begin
197189
setdisplay(; decorations = false)
198190

199191
@test sprint(show, MIME("text/plain"), a) == "[0.0, 2.0] + im*[1.0, 1.0]"
200192
@test sprint(show, MIME("text/plain"), b) == "[0.0, 2.0] - im*[1.0, 1.0]"
201-
@test sprint(show, MIME("text/plain"), c) == "[0.0, 1.00001e-70] - im*[0.999999e-70, 1.00001e-70]"
193+
@test sprint(show, MIME("text/plain"), c) == "[0.0, 1.0e-70] - im*[1.0e-70, 1.0e-70]"
202194
end
203195
end
204196
end
@@ -209,7 +201,7 @@ setprecision(BigFloat, 256) do
209201

210202
@test sprint(show, MIME("text/plain"), a) == "Interval{Float64}(0.0, 2.0, com) + im*Interval{Float64}(1.0, 1.0, com)"
211203
@test sprint(show, MIME("text/plain"), b) == "Interval{Float64}(0.0, 2.0, com) - im*Interval{Float64}(1.0, 1.0, com)"
212-
# @test sprint(show, MIME("text/plain"), c) == "Interval{Float64}(0.0, 2.0, com) + im*Interval{Float64}(1.0, 1.0, com)"
204+
@test sprint(show, MIME("text/plain"), c) == "Interval{Float64}(0.0, 1.0e-70, com) - im*Interval{Float64}(1.0e-70, 1.0e-70, com)"
213205
end
214206

215207
@testset "Midpoint format" begin
@@ -220,15 +212,15 @@ setprecision(BigFloat, 256) do
220212

221213
@test sprint(show, MIME("text/plain"), a) == "(1.0 ± 1.0)_com + im*(1.0 ± 0.0)_com"
222214
@test sprint(show, MIME("text/plain"), b) == "(1.0 ± 1.0)_com - im*(1.0 ± 0.0)_com"
223-
@test sprint(show, MIME("text/plain"), c) == "(5.0e-71 ± 5.00001e-71)_com - im*(1.0e-70 ± 0.0)_com"
215+
@test sprint(show, MIME("text/plain"), c) == "(5.0e-71 ± 5.0e-71)_com - im*(1.0e-70 ± 0.0)_com"
224216
end
225217

226218
@testset "No decorations" begin
227219
setdisplay(; decorations = false)
228220

229221
@test sprint(show, MIME("text/plain"), a) == "(1.0 ± 1.0) + im*(1.0 ± 0.0)"
230222
@test sprint(show, MIME("text/plain"), b) == "(1.0 ± 1.0) - im*(1.0 ± 0.0)"
231-
@test sprint(show, MIME("text/plain"), c) == "(5.0e-71 ± 5.00001e-71) - im*(1.0e-70 ± 0.0)"
223+
@test sprint(show, MIME("text/plain"), c) == "(5.0e-71 ± 5.0e-71) - im*(1.0e-70 ± 0.0)"
232224
end
233225
end
234226
end

0 commit comments

Comments
 (0)