From d6ebe2a70dfcb0fc1677adaf7c29955c690e86ac Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Sun, 13 Sep 2026 23:02:35 -0400 Subject: [PATCH] Run Aqua in tests; fix Bool conversions and rounding Aqua found a method ambiguity between the generic (::Type{I<:Integer})(x::DecimalFloatingPoint) constructor and Base.Bool(::Real), and a missing compat entry for Test. Fixing the ambiguity surfaced related Bool bugs: DecXX(true) went through string parsing and failed, and trunc/floor/ceil/round(Bool, x) either hit an ambiguity (Julia < 1.11) or threw InexactError from Bool(10) in the generic integer path (Julia >= 1.11). - Bool(x::DecimalFloatingPoint) with Base's semantics (0 -> false, 1 -> true, else InexactError) - DecXX(x::Bool) via the Int32 path - trunc/floor/ceil/round(Bool, x) via Int - Test compat entry; Aqua added to the test target and run in runtests.jl Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_014GD7jbSks8x6h6QThUrhk3 --- .gitignore | 2 ++ Project.toml | 5 ++++- src/DecFP.jl | 9 ++++++++- test/runtests.jl | 13 +++++++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index b6f8b8d..89de351 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ *.jl.cov +*.jl.*.cov *.jl.mem +*.jl.*.mem Manifest.toml diff --git a/Project.toml b/Project.toml index 3f6b5a8..500015c 100644 --- a/Project.toml +++ b/Project.toml @@ -14,10 +14,13 @@ SpecialFunctions = "0.8, 0.9, 0.10, 0.11, 1, 2" julia = "1.7" Printf = "<0.0.1, 1" Random = "<0.0.1, 1" +Test = "<0.0.1, 1" +Aqua = "0.8" [extras] +Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test", "Printf"] +test = ["Test", "Printf", "Aqua"] diff --git a/src/DecFP.jl b/src/DecFP.jl index 782eea9..9d8008c 100644 --- a/src/DecFP.jl +++ b/src/DecFP.jl @@ -204,7 +204,7 @@ for w in (32,64,128) @eval $BID(x::AbstractIrrational, r::RoundingMode) = $BID(string(BigFloat(x, precision=256)), r) - @eval $BID(x::Union{Int8,UInt8,Int16,UInt16}) = $BID(Int32(x)) + @eval $BID(x::Union{Bool,Int8,UInt8,Int16,UInt16}) = $BID(Int32(x)) @eval $BID(x::Float16) = $BID(Float32(x)) @eval $BID(x::Rational{T}) where {T} = $BID(x.num) / $BID(x.den) @@ -584,6 +584,13 @@ end Base.Signed(x::DecimalFloatingPoint) = Int(x) Base.Unsigned(x::DecimalFloatingPoint) = UInt(x) Base.Integer(x::DecimalFloatingPoint) = Int(x) +Base.Bool(x::DecimalFloatingPoint) = x == 0 ? false : x == 1 ? true : throw(InexactError(:Bool, Bool, x)) + +# The generic ::Type{I<:Integer} methods above construct I(10), which fails for Bool, and on +# Julia < 1.11 they are also ambiguous with Base's (::Type{Bool}, ::AbstractFloat) methods. +for f in (:trunc, :floor, :ceil, :round) + @eval Base.$f(::Type{Bool}, x::DecimalFloatingPoint) = Bool($f(Int, x)) +end function (::Type{I})(x::DecimalFloatingPoint) where {I<:Integer} x != trunc(x) && throw(InexactError(:convert, I, x)) diff --git a/test/runtests.jl b/test/runtests.jl index 5b516d5..6a1748b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,9 @@ using DecFP, Test, Printf, Random, Base.MathConstants, SpecialFunctions +using Aqua + +@testset "Aqua" begin + Aqua.test_all(DecFP) +end include("printf.jl") @@ -361,6 +366,14 @@ for T in (Dec32, Dec64, Dec128) @test round(T(2.5), RoundNearestTiesAway) === round(T(3.3), RoundNearestTiesAway) === T(3) @test round(T(2.5), RoundNearestTiesUp) === round(T(3.3), RoundNearestTiesUp) === T(3) + @test T(true) === T(1) && T(false) === T(0) + @test Bool(T(1)) === true && Bool(T(0)) === false && Bool(-T(0)) === false + @test_throws InexactError Bool(T(2)) + @test_throws InexactError Bool(T(NaN)) + @test trunc(Bool, T(1.5)) === floor(Bool, T(1.5)) === round(Bool, T(1.2)) === ceil(Bool, T(0.5)) === true + @test trunc(Bool, T(-0.5)) === floor(Bool, T(0.5)) === round(Bool, T(0.2)) === ceil(Bool, T(-0.5)) === false + @test_throws InexactError trunc(Bool, T(2)) + @test_throws InexactError floor(Bool, T(-1)) for Ti in (Integer,Int8,UInt8,Int16,UInt16,Int32,UInt32,Int64,UInt64,Int128,UInt128) if Ti != Integer @test parse(T, "17") == T(Ti(17)) == Ti(17) == Ti(T(17))