Skip to content
This repository has been archived by the owner on Mar 1, 2024. It is now read-only.

Formatting fails for typemin(T<:Integer) #110

Open
jagot opened this issue Mar 28, 2023 · 2 comments
Open

Formatting fails for typemin(T<:Integer) #110

jagot opened this issue Mar 28, 2023 · 2 comments

Comments

@jagot
Copy link

jagot commented Mar 28, 2023

Consider

f = FormatExpr("{1:+d}")
for T in (Int8,Int16,Int32,Int64)
    @test format(f, typemin(T)) == string(typemin(T)) # Crashes
    @test format(f, typemax(T)) == "+"*string(typemax(T)) # Works
end

The first test (for typemin) crashes with the error

Error During Test at REPL[26]:2
  Test threw exception
  Expression: format(f, typemin(T)) == string(typemin(T))
  InexactError: check_top_bit(UInt32, -80)
  Stacktrace:
    [1] throw_inexacterror(f::Symbol, #unused#::Type{UInt32}, val::Int32)
      @ Core ./boot.jl:614
    [2] check_top_bit
      @ ./boot.jl:628 [inlined]
    [3] toUInt32
      @ ./boot.jl:727 [inlined]
    [4] UInt32
      @ ./boot.jl:768 [inlined]
    [5] +
      @ ./char.jl:242 [inlined]
    [6] _digitchar
      @ ~/.julia/packages/Formatting/BwWBf/src/fmtcore.jl:63 [inlined]
    [7] _pfmt_intdigits(out::IOBuffer, ax::Int8, op::Formatting._Dec)
      @ Formatting ~/.julia/packages/Formatting/BwWBf/src/fmtcore.jl:102
    [8] _pfmt_int(out::IOBuffer, sch::Char, ip::String, zs::Int64, ax::Int8, op::Formatting._Dec)
      @ Formatting ~/.julia/packages/Formatting/BwWBf/src/fmtcore.jl:89
    [9] _pfmt_i(out::IOBuffer, fs::FormatSpec, x::Int8, op::Formatting._Dec)
      @ Formatting ~/.julia/packages/Formatting/BwWBf/src/fmtcore.jl:126
   [10] printfmt(io::IOBuffer, fs::FormatSpec, x::Int8)
      @ Formatting ~/.julia/packages/Formatting/BwWBf/src/fmtspec.jl:182
   [11] printfmt(io::IOBuffer, fe::FormatExpr, args::Int8)
      @ Formatting ~/.julia/packages/Formatting/BwWBf/src/formatexpr.jl:147
   [12] sprint(::Function, ::FormatExpr, ::Vararg{Any}; context::Nothing, sizehint::Int64)
      @ Base ./strings/io.jl:114
   [13] sprint
      @ ./strings/io.jl:107 [inlined]
   [14] format(fe::FormatExpr, args::Int8)
      @ Formatting ~/.julia/packages/Formatting/BwWBf/src/formatexpr.jl:165
@jagot
Copy link
Author

jagot commented Mar 28, 2023

Digging a bit, it fails because we cannot compute the absolute value of typemin(i::Integer), since in two-complement binary representation, the absolute value of the minimum number is one larger than the maximum number:

julia> abs(typemin(Int8))
-128

This makes the following logic break:

function _pfmt_i(out::IO, fs::FormatSpec, x::Integer, op::Op) where {Op}
# calculate actual length
ax = abs(x)
xlen = _ndigits(abs(x), op)
# sign char
sch = _signchar(x, fs.sign)
if sch != '\0'
xlen += 1
end
# prefix (e.g. 0x, 0b, 0o)
ip = ""
if fs.ipre
ip = _ipre(op)
xlen += length(ip)
end
# printing
wid = fs.width
if wid <= xlen
_pfmt_int(out, sch, ip, 0, ax, op)
elseif fs.zpad
_pfmt_int(out, sch, ip, wid-xlen, ax, op)
else
a = fs.align
if a == '<'
_pfmt_int(out, sch, ip, 0, ax, op)
_repprint(out, fs.fill, wid-xlen)
else
_repprint(out, fs.fill, wid-xlen)
_pfmt_int(out, sch, ip, 0, ax, op)
end
end
end

@ScottPJones
Copy link
Collaborator

Note that this is not broken if you use Format instead of Formatting

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants