Skip to content

Commit

Permalink
Fix rounding with digits/sigdigits (#308)
Browse files Browse the repository at this point in the history
  • Loading branch information
sostock authored Feb 22, 2020
1 parent 7526dc7 commit f6866ea
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 15 deletions.
33 changes: 18 additions & 15 deletions src/quantities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,9 @@ _rounderr() = error("specify the type of the quantity to convert to ",
"when rounding quantities. Example: round(typeof(1u\"m\"), 137u\"cm\").")

# convenience methods
round(u::Units, q::Quantity, r::RoundingMode=RoundNearest; kwargs...) =
round(numtype(q), u, q, r; kwargs...)
round(::Type{T}, u::Units, q::Quantity, r::RoundingMode=RoundNearest;
round(u::Units, q::AbstractQuantity, r::RoundingMode=RoundNearest; kwargs...) =
Quantity(round(ustrip(u, q), r; kwargs...), u)
round(::Type{T}, u::Units, q::AbstractQuantity, r::RoundingMode=RoundNearest;
kwargs...) where {T<:Number} =
round(Quantity{T, dimension(u), typeof(u)}, q, r; kwargs...)

Expand All @@ -297,23 +297,26 @@ round(::Type{T}, x::AbstractQuantity, r=RoundingMode=RoundNearest;
kwargs...) where {T<:Number} = _dimerr(:round)
round(::Type{T}, x::DimensionlessQuantity, r::RoundingMode=RoundNearest;
kwargs...) where {T<:Number} = round(T, uconvert(NoUnits, x), r; kwargs...)
function round(::Type{T}, x::Quantity, r::RoundingMode=RoundNearest;
function round(::Type{T}, x::AbstractQuantity;
kwargs...) where {S, T <: Quantity{S}}
u = unit(T)
unitless = ustrip(uconvert(u, x))
return Quantity{S, dimension(T), typeof(u)}(round(float(unitless), r; kwargs...))
unitless = ustrip(u, x)
return Quantity{S, dimension(T), typeof(u)}(round(unitless; kwargs...))
end
function round(::Type{T}, x::AbstractQuantity, r::RoundingMode;
kwargs...) where {S, T <: Quantity{S}}
u = unit(T)
unitless = ustrip(u, x)
return Quantity{S, dimension(T), typeof(u)}(round(unitless, r; kwargs...))
end

# that should actually be fixed in Base ↓
trunc(x::AbstractQuantity; kwargs...) = round(x, RoundToZero; kwargs...)
floor(x::AbstractQuantity; kwargs...) = round(x, RoundDown; kwargs...)
ceil(x::AbstractQuantity; kwargs...) = round(x, RoundUp; kwargs...)
trunc(::Type{T}, x::AbstractQuantity; kwargs...) where {T<:Number} =
round(T, x, RoundToZero; kwargs...)
floor(::Type{T}, x::AbstractQuantity; kwargs...) where {T<:Number} =
round(T, x, RoundDown; kwargs...)
ceil(::Type{T}, x::AbstractQuantity; kwargs...) where {T<:Number} =
round(T, x, RoundUp; kwargs...)
for (f,r) = ((:trunc, :RoundToZero), (:floor, :RoundDown), (:ceil, :RoundUp))
@eval $f(x::AbstractQuantity; kwargs...) = round(x, $r; kwargs...)
@eval $f(::Type{T}, x::AbstractQuantity; kwargs...) where {T<:Number} =
round(T, x, $r; kwargs...)
@eval $f(u::Units, x::AbstractQuantity; kwargs...) = round(u, x, $r; kwargs...)
end

zero(x::AbstractQuantity) = Quantity(zero(x.val), unit(x))
zero(x::AffineQuantity) = Quantity(zero(x.val), absoluteunit(x))
Expand Down
10 changes: 10 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,16 @@ end
@test round(Int, u"inch", 1.0314m) === 41u"inch"
@test round(typeof(1m), 137cm) === 1m
@test round(137cm/m) === 1//1
@test round(u"m", -125u"cm", sigdigits=2) === -1.2u"m"
@test round(u"m", (125//1)u"cm", sigdigits=2) === 1.2u"m"
@test round(u"m", -125u"cm", RoundNearestTiesUp, sigdigits=2) === -1.2u"m"
@test round(u"m", (125//1)u"cm", RoundNearestTiesUp, sigdigits=2) === 1.3u"m"
@test floor(u"m", -125u"cm", sigdigits=2) === -1.3u"m"
@test floor(u"m", (125//1)u"cm", sigdigits=2) === 1.2u"m"
@test ceil(u"m", -125u"cm", sigdigits=2) === -1.2u"m"
@test ceil(u"m", (125//1)u"cm", sigdigits=2) === 1.3u"m"
@test trunc(u"m", -125u"cm", sigdigits=2) === -1.2u"m"
@test trunc(u"m", (125//1)u"cm", sigdigits=2) === 1.2u"m"
end

@testset "Sgn, abs, &c." begin
Expand Down

0 comments on commit f6866ea

Please sign in to comment.