diff --git a/base/Base.jl b/base/Base.jl index 0673a1081ae69..4fb29672f35d7 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -222,7 +222,6 @@ include(strcat((length(Core.ARGS)>=2 ? Core.ARGS[2] : ""), "version_git.jl")) # # numeric operations include("hashing.jl") include("rounding.jl") -using .Rounding include("div.jl") include("rawbigints.jl") include("float.jl") diff --git a/base/boot.jl b/base/boot.jl index e24a6f4ffc0e0..366d584d78b73 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -328,9 +328,8 @@ TypeError(where, @nospecialize(expected::Type), @nospecialize(got)) = TypeError(Symbol(where), "", expected, got) struct InexactError <: Exception func::Symbol - T # Type - val - InexactError(f::Symbol, @nospecialize(T), @nospecialize(val)) = (@noinline; new(f, T, val)) + args + InexactError(f::Symbol, @nospecialize(args...)) = (@noinline; new(f, args)) end struct OverflowError <: Exception msg::AbstractString @@ -630,8 +629,6 @@ eval(Core, :(NamedTuple{names,T}(args::T) where {names, T <: Tuple} = import .Intrinsics: eq_int, trunc_int, lshr_int, sub_int, shl_int, bitcast, sext_int, zext_int, and_int -throw_inexacterror(f::Symbol, ::Type{T}, val) where {T} = (@noinline; throw(InexactError(f, T, val))) - function is_top_bit_set(x) @inline eq_int(trunc_int(UInt8, lshr_int(x, sub_int(shl_int(sizeof(x), 3), 1))), trunc_int(UInt8, 1)) @@ -642,6 +639,9 @@ function is_top_bit_set(x::Union{Int8,UInt8}) eq_int(lshr_int(x, 7), trunc_int(typeof(x), 1)) end +#TODO delete this function (but see #48097): +throw_inexacterror(args...) = throw(InexactError(args...)) + function check_top_bit(::Type{To}, x) where {To} @inline is_top_bit_set(x) && throw_inexacterror(:check_top_bit, To, x) diff --git a/base/errorshow.jl b/base/errorshow.jl index 8f54fc94a5f84..39cdf14d34de8 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -173,8 +173,10 @@ end function showerror(io::IO, ex::InexactError) print(io, "InexactError: ", ex.func, '(') - nameof(ex.T) === ex.func || print(io, ex.T, ", ") - print(io, ex.val, ')') + T = first(ex.args) + nameof(T) === ex.func || print(io, T, ", ") + join(io, ex.args[2:end], ", ") + print(io, ")") Experimental.show_error_hints(io, ex) end diff --git a/base/float.jl b/base/float.jl index d644f3237ef15..3e6e39c5951d8 100644 --- a/base/float.jl +++ b/base/float.jl @@ -436,21 +436,15 @@ unsafe_trunc(::Type{UInt128}, x::Float16) = unsafe_trunc(UInt128, Float32(x)) unsafe_trunc(::Type{Int128}, x::Float16) = unsafe_trunc(Int128, Float32(x)) # matches convert methods -# also determines floor, ceil, round -trunc(::Type{Signed}, x::IEEEFloat) = trunc(Int,x) -trunc(::Type{Unsigned}, x::IEEEFloat) = trunc(UInt,x) -trunc(::Type{Integer}, x::IEEEFloat) = trunc(Int,x) - -# Bool -trunc(::Type{Bool}, x::AbstractFloat) = (-1 < x < 2) ? 1 <= x : throw(InexactError(:trunc, Bool, x)) -floor(::Type{Bool}, x::AbstractFloat) = (0 <= x < 2) ? 1 <= x : throw(InexactError(:floor, Bool, x)) -ceil(::Type{Bool}, x::AbstractFloat) = (-1 < x <= 1) ? 0 < x : throw(InexactError(:ceil, Bool, x)) -round(::Type{Bool}, x::AbstractFloat) = (-0.5 <= x < 1.5) ? 0.5 < x : throw(InexactError(:round, Bool, x)) - -round(x::IEEEFloat, r::RoundingMode{:ToZero}) = trunc_llvm(x) -round(x::IEEEFloat, r::RoundingMode{:Down}) = floor_llvm(x) -round(x::IEEEFloat, r::RoundingMode{:Up}) = ceil_llvm(x) -round(x::IEEEFloat, r::RoundingMode{:Nearest}) = rint_llvm(x) +# also determines trunc, floor, ceil +round(::Type{Signed}, x::IEEEFloat, r::RoundingMode) = round(Int, x, r) +round(::Type{Unsigned}, x::IEEEFloat, r::RoundingMode) = round(UInt, x, r) +round(::Type{Integer}, x::IEEEFloat, r::RoundingMode) = round(Int, x, r) + +round(x::IEEEFloat, ::RoundingMode{:ToZero}) = trunc_llvm(x) +round(x::IEEEFloat, ::RoundingMode{:Down}) = floor_llvm(x) +round(x::IEEEFloat, ::RoundingMode{:Up}) = ceil_llvm(x) +round(x::IEEEFloat, ::RoundingMode{:Nearest}) = rint_llvm(x) ## floating point promotions ## promote_rule(::Type{Float32}, ::Type{Float16}) = Float32 @@ -931,11 +925,11 @@ for Ti in (Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UIn # directly. `Tf(typemax(Ti))+1` is either always exactly representable, or # rounded to `Inf` (e.g. when `Ti==UInt128 && Tf==Float32`). @eval begin - function trunc(::Type{$Ti},x::$Tf) + function round(::Type{$Ti},x::$Tf,::RoundingMode{:ToZero}) if $(Tf(typemin(Ti))-one(Tf)) < x < $(Tf(typemax(Ti))+one(Tf)) return unsafe_trunc($Ti,x) else - throw(InexactError(:trunc, $Ti, x)) + throw(InexactError(:round, $Ti, x, RoundToZero)) end end function (::Type{$Ti})(x::$Tf) @@ -955,11 +949,11 @@ for Ti in (Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UIn # be rounded up. This assumes that `Tf(typemin(Ti)) > -Inf`, which is true for # these types, but not for `Float16` or larger integer types. @eval begin - function trunc(::Type{$Ti},x::$Tf) + function round(::Type{$Ti},x::$Tf,::RoundingMode{:ToZero}) if $(Tf(typemin(Ti))) <= x < $(Tf(typemax(Ti))) return unsafe_trunc($Ti,x) else - throw(InexactError(:trunc, $Ti, x)) + throw(InexactError(:round, $Ti, x, RoundToZero)) end end function (::Type{$Ti})(x::$Tf) diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index 67e7cbfca62d0..a2a0f60bcf399 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -46,11 +46,6 @@ isinteger(x::AbstractFloat) = (x - trunc(x) == 0) # See rounding.jl for docstring. -function round(::Type{T}, x::AbstractFloat, r::RoundingMode) where {T<:Integer} - r != RoundToZero && (x = round(x,r)) - trunc(T, x) -end - # NOTE: this relies on the current keyword dispatch behaviour (#9498). function round(x::Real, r::RoundingMode=RoundNearest; digits::Union{Nothing,Integer}=nothing, sigdigits::Union{Nothing,Integer}=nothing, base::Union{Nothing,Integer}=nothing) @@ -77,20 +72,6 @@ function round(x::Real, r::RoundingMode=RoundNearest; end end -trunc(x::Real; kwargs...) = round(x, RoundToZero; kwargs...) -floor(x::Real; kwargs...) = round(x, RoundDown; kwargs...) -ceil(x::Real; kwargs...) = round(x, RoundUp; kwargs...) - -# fallbacks -trunc(::Type{T}, x::Real; kwargs...) where {T} = round(T, x, RoundToZero; kwargs...) -floor(::Type{T}, x::Real; kwargs...) where {T} = round(T, x, RoundDown; kwargs...) -ceil(::Type{T}, x::Real; kwargs...) where {T} = round(T, x, RoundUp; kwargs...) -round(::Type{T}, x::Real; kwargs...) where {T} = round(T, x, RoundNearest; kwargs...) - -round(::Type{T}, x::Real, r::RoundingMode) where {T} = convert(T, round(x, r)) - -round(x::Integer, r::RoundingMode) = x - # round x to multiples of 1/invstep function _round_invstep(x, invstep, r::RoundingMode) y = round(x * invstep, r) / invstep diff --git a/base/gmp.jl b/base/gmp.jl index 995b62e6e1bdb..ead80b56541a6 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -320,7 +320,7 @@ function BigInt(x::Float64) unsafe_trunc(BigInt,x) end -function trunc(::Type{BigInt}, x::Union{Float16,Float32,Float64}) +function round(::Type{BigInt}, x::Union{Float16,Float32,Float64}, r::RoundingMode{:ToZero}) isfinite(x) || throw(InexactError(:trunc, BigInt, x)) unsafe_trunc(BigInt,x) end diff --git a/base/int.jl b/base/int.jl index 05457d9cf55c3..61576d4360835 100644 --- a/base/int.jl +++ b/base/int.jl @@ -629,70 +629,6 @@ mod(x::Integer, ::Type{T}) where {T<:Integer} = rem(x, T) unsafe_trunc(::Type{T}, x::Integer) where {T<:Integer} = rem(x, T) -""" - trunc([T,] x) - trunc(x; digits::Integer= [, base = 10]) - trunc(x; sigdigits::Integer= [, base = 10]) - -`trunc(x)` returns the nearest integral value of the same type as `x` whose absolute value -is less than or equal to the absolute value of `x`. - -`trunc(T, x)` converts the result to type `T`, throwing an `InexactError` if the truncated -value is not representable a `T`. - -Keywords `digits`, `sigdigits` and `base` work as for [`round`](@ref). - -See also: [`%`](@ref rem), [`floor`](@ref), [`unsigned`](@ref), [`unsafe_trunc`](@ref). - -# Examples -```jldoctest -julia> trunc(2.22) -2.0 - -julia> trunc(-2.22, digits=1) --2.2 - -julia> trunc(Int, -2.22) --2 -``` -""" -function trunc end - -""" - floor([T,] x) - floor(x; digits::Integer= [, base = 10]) - floor(x; sigdigits::Integer= [, base = 10]) - -`floor(x)` returns the nearest integral value of the same type as `x` that is less than or -equal to `x`. - -`floor(T, x)` converts the result to type `T`, throwing an `InexactError` if the floored -value is not representable a `T`. - -Keywords `digits`, `sigdigits` and `base` work as for [`round`](@ref). -""" -function floor end - -""" - ceil([T,] x) - ceil(x; digits::Integer= [, base = 10]) - ceil(x; sigdigits::Integer= [, base = 10]) - -`ceil(x)` returns the nearest integral value of the same type as `x` that is greater than or -equal to `x`. - -`ceil(T, x)` converts the result to type `T`, throwing an `InexactError` if the ceiled -value is not representable as a `T`. - -Keywords `digits`, `sigdigits` and `base` work as for [`round`](@ref). -""" -function ceil end - -round(::Type{T}, x::Integer) where {T<:Integer} = convert(T, x) -trunc(::Type{T}, x::Integer) where {T<:Integer} = convert(T, x) -floor(::Type{T}, x::Integer) where {T<:Integer} = convert(T, x) - ceil(::Type{T}, x::Integer) where {T<:Integer} = convert(T, x) - ## integer construction ## """ diff --git a/base/missing.jl b/base/missing.jl index f0cad70690ebe..35e1b4034643c 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -150,19 +150,6 @@ round(::Type{T}, x::Real, r::RoundingMode=RoundNearest) where {T>:Missing} = rou round(::Type{T}, x::Rational{Tr}, r::RoundingMode=RoundNearest) where {T>:Missing,Tr} = round(nonmissingtype_checked(T), x, r) round(::Type{T}, x::Rational{Bool}, r::RoundingMode=RoundNearest) where {T>:Missing} = round(nonmissingtype_checked(T), x, r) -# Handle ceil, floor, and trunc separately as they have no RoundingMode argument -for f in (:(ceil), :(floor), :(trunc)) - @eval begin - ($f)(::Missing; sigdigits::Integer=0, digits::Integer=0, base::Integer=0) = missing - ($f)(::Type{>:Missing}, ::Missing) = missing - ($f)(::Type{T}, ::Missing) where {T} = throw(MissingException(missing_conversion_msg(T))) - ($f)(::Type{T}, x::Any) where {T>:Missing} = $f(nonmissingtype_checked(T), x) - # to fix ambiguities - ($f)(::Type{T}, x::Rational) where {T>:Missing} = $f(nonmissingtype_checked(T), x) - ($f)(::Type{T}, x::Real) where {T>:Missing} = $f(nonmissingtype_checked(T), x) - end -end - # to avoid ambiguity warnings (^)(::Missing, ::Integer) = missing diff --git a/base/mpfr.jl b/base/mpfr.jl index b349f405cda93..dc1285ec42f23 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -380,18 +380,15 @@ round(::Type{T}, x::BigFloat, r::RoundingMode) where T<:Union{Signed, Unsigned} invoke(round, Tuple{Type{<:Union{Signed, Unsigned}}, BigFloat, Union{RoundingMode, MPFRRoundingMode}}, T, x, r) round(::Type{BigInt}, x::BigFloat, r::RoundingMode) = invoke(round, Tuple{Type{BigInt}, BigFloat, Union{RoundingMode, MPFRRoundingMode}}, BigInt, x, r) -round(::Type{<:Integer}, x::BigFloat, r::RoundingMode) = throw(MethodError(round, (Integer, x, r))) unsafe_trunc(::Type{T}, x::BigFloat) where {T<:Integer} = unsafe_trunc(T, _unchecked_cast(T, x, RoundToZero)) unsafe_trunc(::Type{BigInt}, x::BigFloat) = _unchecked_cast(BigInt, x, RoundToZero) -# TODO: Ideally the base fallbacks for these would already exist -for (f, rnd) in zip((:trunc, :floor, :ceil, :round), - (RoundToZero, RoundDown, RoundUp, :(ROUNDING_MODE[]))) - @eval $f(::Type{T}, x::BigFloat) where T<:Union{Unsigned, Signed, BigInt} = round(T, x, $rnd) - @eval $f(::Type{Integer}, x::BigFloat) = $f(BigInt, x) -end +round(::Type{T}, x::BigFloat) where T<:Integer = round(T, x, ROUNDING_MODE[]) +# these two methods are split to increase their precedence in disambiguation: +round(::Type{Integer}, x::BigFloat, r::RoundingMode) = round(BigInt, x, r) +round(::Type{Integer}, x::BigFloat, r::MPFRRoundingMode) = round(BigInt, x, r) function Bool(x::BigFloat) iszero(x) && return false diff --git a/base/rounding.jl b/base/rounding.jl index ddbc5fbc7809b..2da605bc36f8f 100644 --- a/base/rounding.jl +++ b/base/rounding.jl @@ -283,6 +283,8 @@ function _convert_rounding(::Type{T}, x::Real, r::RoundingMode{:ToZero}) where T end end +# Default definitions + """ set_zero_subnormals(yes::Bool) -> Bool @@ -313,8 +315,8 @@ for IEEE arithmetic, and `true` if they might be converted to zeros. get_zero_subnormals() = ccall(:jl_get_zero_subnormals,Int32,())!=0 end #module +using .Rounding -# Docstring listed here so it appears above the complex docstring. """ round([T,] x, [r::RoundingMode]) round(x, [r::RoundingMode]; digits::Integer=0, base = 10) @@ -388,4 +390,83 @@ julia> round(357.913; sigdigits=4, base=2) To extend `round` to new numeric types, it is typically sufficient to define `Base.round(x::NewType, r::RoundingMode)`. """ -round(T::Type, x) +function round end + +""" + trunc([T,] x) + trunc(x; digits::Integer= [, base = 10]) + trunc(x; sigdigits::Integer= [, base = 10]) + +`trunc(x)` returns the nearest integral value of the same type as `x` whose absolute value +is less than or equal to the absolute value of `x`. + +`trunc(T, x)` converts the result to type `T`, throwing an `InexactError` if the truncated +value is not representable a `T`. + +Keywords `digits`, `sigdigits` and `base` work as for [`round`](@ref). + +To support `trunc` for a new type, define `Base.round(x::NewType, ::RoundingMode{:ToZero})`. + +See also: [`%`](@ref rem), [`floor`](@ref), [`unsigned`](@ref), [`unsafe_trunc`](@ref). + +# Examples +```jldoctest +julia> trunc(2.22) +2.0 + +julia> trunc(-2.22, digits=1) +-2.2 + +julia> trunc(Int, -2.22) +-2 +``` +""" +function trunc end + +""" + floor([T,] x) + floor(x; digits::Integer= [, base = 10]) + floor(x; sigdigits::Integer= [, base = 10]) + +`floor(x)` returns the nearest integral value of the same type as `x` that is less than or +equal to `x`. + +`floor(T, x)` converts the result to type `T`, throwing an `InexactError` if the floored +value is not representable a `T`. + +Keywords `digits`, `sigdigits` and `base` work as for [`round`](@ref). + +To support `floor` for a new type, define `Base.round(x::NewType, ::RoundingMode{:Down})`. +""" +function floor end + +""" + ceil([T,] x) + ceil(x; digits::Integer= [, base = 10]) + ceil(x; sigdigits::Integer= [, base = 10]) + +`ceil(x)` returns the nearest integral value of the same type as `x` that is greater than or +equal to `x`. + +`ceil(T, x)` converts the result to type `T`, throwing an `InexactError` if the ceiled +value is not representable as a `T`. + +Keywords `digits`, `sigdigits` and `base` work as for [`round`](@ref). + +To support `ceil` for a new type, define `Base.round(x::NewType, ::RoundingMode{:Up})`. +""" +function ceil end + +trunc(x; kws...) = round(x, RoundToZero; kws...) +floor(x; kws...) = round(x, RoundDown; kws...) + ceil(x; kws...) = round(x, RoundUp; kws...) +round(x; kws...) = round(x, RoundNearest; kws...) + +trunc(::Type{T}, x) where T = round(T, x, RoundToZero) +floor(::Type{T}, x) where T = round(T, x, RoundDown) + ceil(::Type{T}, x) where T = round(T, x, RoundUp) +round(::Type{T}, x) where T = round(T, x, RoundNearest) + +round(::Type{T}, x, r::RoundingMode) where T = convert(T, round(x, r)) + +round(x::Integer, r::RoundingMode) = x diff --git a/doc/src/base/math.md b/doc/src/base/math.md index 62368424629c6..573a2fc0d7e90 100644 --- a/doc/src/base/math.md +++ b/doc/src/base/math.md @@ -118,7 +118,7 @@ Base.exp10 Base.Math.ldexp Base.Math.modf Base.expm1 -Base.round(::Type, ::Any) +Base.round Base.Rounding.RoundingMode Base.Rounding.RoundNearest Base.Rounding.RoundNearestTiesAway diff --git a/doc/src/manual/interfaces.md b/doc/src/manual/interfaces.md index 6cad44f12a089..ac56a2fb2e3a4 100644 --- a/doc/src/manual/interfaces.md +++ b/doc/src/manual/interfaces.md @@ -836,3 +836,51 @@ julia> p.r Finally, it is worth noting that adding instance properties like this is quite rarely done in Julia and should in general only be done if there is a good reason for doing so. + +## [Rounding](@id man-rounding-interface) + +| Methods to implement | Default definition | Brief description | +|:--------------------------------------------- |:------------------------- |:--------------------------------------------------------------------------------------------------- | +| `round(x::ObjType, r::RoundingMode)` | none | Round `x` and return the result. If possible, round should return an object of the same type as `x` | +| `round(T::Type, x::ObjType, r::RoundingMode)` | `convert(T, round(x, r))` | Round `x`, returning the result as a `T` | + +To support rounding on a new type it is typically sufficient to define the single method +`round(x::ObjType, r::RoundingMode)`. The passed rounding mode determines in which direction +the value should be rounded. The most commonly used rounding modes are `RoundNearest`, +`RoundToZero`, `RoundDown`, and `RoundUp`, as these rounding modes are used in the +definitions of the one argument `round`, method, and `trunc`, `floor`, and `ceil`, +respectively. + +In some cases, it is possible to define a three-argument `round` method that is more +accurate or performant than the two-argument method followed by conversion. In this case it +is acceptable to define the three argument method in addition to the two argument method. +If it is impossible to represent the rounded result as an object of the type `T`, +then the three argument method should throw an `InexactError`. + +For example, if we have an `Interval` type which represents a range of possible values +similar to https://github.com/JuliaPhysics/Measurements.jl, we may define rounding on that +type with the following + +```jldoctest +julia> struct Interval{T} + min::T + max::T + end + +julia> Base.round(x::Interval, r::RoundingMode) = Interval(round(x.min, r), round(x.max, r)) + +julia> x = Interval(1.7, 2.2) +Interval{Float64}(1.7, 2.2) + +julia> round(x) +Interval{Float64}(2.0, 2.0) + +julia> floor(x) +Interval{Float64}(1.0, 2.0) + +julia> ceil(x) +Interval{Float64}(2.0, 3.0) + +julia> trunc(x) +Interval{Float64}(1.0, 2.0) +``` diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index c808b14f10e0e..59af063ce8487 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -502,7 +502,7 @@ julia> round(Int8,127.4) 127 julia> round(Int8,127.6) -ERROR: InexactError: trunc(Int8, 128.0) +ERROR: InexactError: Int8(128.0) Stacktrace: [...] ``` diff --git a/test/floatfuncs.jl b/test/floatfuncs.jl index 8ca5c3836529f..cc29052d722f3 100644 --- a/test/floatfuncs.jl +++ b/test/floatfuncs.jl @@ -271,7 +271,7 @@ end result = result !== error && typemin(Ti) <= result <= typemax(Ti) ? result : error if result === error - # @test_throws InexactError round(Ti, z) Broken because of #51113 + @test_throws InexactError round(Ti, z) @test_throws InexactError Ti(z) else @test result == round(Ti, z) diff --git a/test/rounding.jl b/test/rounding.jl index 6aa72936998c8..d0d59b2568c3a 100644 --- a/test/rounding.jl +++ b/test/rounding.jl @@ -352,6 +352,38 @@ end end end +@testset "rounding floats with specified return type #50778" begin + @test round(Float64, 1.2) === 1.0 + @test round(Float32, 1e60) === Inf32 + x = floatmax(Float32)-1.0 + @test round(Float32, x) == x +end + +@testset "rounding complex numbers (#42060, #47128)" begin + # 42060 + @test ceil(Complex(4.6, 2.2)) === Complex(5.0, 3.0) + @test floor(Complex(4.6, 2.2)) === Complex(4.0, 2.0) + @test trunc(Complex(4.6, 2.2)) === Complex(4.0, 2.0) + @test round(Complex(4.6, 2.2)) === Complex(5.0, 2.0) + @test ceil(Complex(-4.6, -2.2)) === Complex(-4.0, -2.0) + @test floor(Complex(-4.6, -2.2)) === Complex(-5.0, -3.0) + @test trunc(Complex(-4.6, -2.2)) === Complex(-4.0, -2.0) + @test round(Complex(-4.6, -2.2)) === Complex(-5.0, -2.0) + + # 47128 + @test round(Complex{Int}, Complex(4.6, 2.2)) === Complex(5, 2) + @test ceil(Complex{Int}, Complex(4.6, 2.2)) === Complex(5, 3) +end + +@testset "rounding to custom integers" begin + struct Int50812 <: Integer + x::Int + end + @test round(Int50812, 1.2) === Int50812(1) + @test round(Int50812, π) === Int50812(3) + @test ceil(Int50812, π) === Int50812(4) +end + const MPFRRM = Base.MPFR.MPFRRoundingMode function mpfr_to_ieee(::Type{Float32}, x::BigFloat, r::MPFRRM) @@ -416,3 +448,10 @@ const native_rounding_modes = ( end end end + +@testset "round(Int, -Inf16) should throw (#51113)" begin + @test_throws InexactError round(Int32, -Inf16) + @test_throws InexactError round(Int64, -Inf16) + @test_throws InexactError round(Int128, -Inf16) + # More comprehensive testing is present in test/floatfuncs.jl +end