Skip to content

Commit fa45e36

Browse files
committed
Revise rounding tests
1 parent dab3874 commit fa45e36

File tree

2 files changed

+37
-31
lines changed

2 files changed

+37
-31
lines changed

src/FixedPointDecimals.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,8 @@ function round{T, f}(::Type{FD{T, f}}, x::Real, ::RoundingMode{:Nearest}=RoundNe
199199
end
200200

201201
# needed to avoid ambiguity
202-
function round{T, f}(::Type{FD{T, f}}, x::Rational,
203-
::RoundingMode{:Nearest}=RoundNearest)
204-
reinterpret(FD{T, f}, round(T, T(10)^f * x))
202+
function round{T, f}(::Type{FD{T, f}}, x::Rational, ::RoundingMode{:Nearest}=RoundNearest)
203+
reinterpret(FD{T, f}, round(T, x * coefficient(FD{T, f})))
205204
end
206205

207206
# conversions and promotions

test/runtests.jl

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,13 @@ function parse_int{T, f}(::Type{FD{T, f}}, val::AbstractString; ceil::Bool=false
6767
reinterpret(FD{T, f}, parse(T, val[1:(f + 1)]) + T(ceil))
6868
end
6969

70+
# When working with typemax of Int128 or UInt128 we can run into issues.
71+
# https://github.com/JuliaLang/julia/pull/19779
72+
if VERSION < v"0.6.0-dev.1849"
73+
Base.:/(x::Int128, y::BigInt) = /(promote(x, y)...)
74+
Base.:/(x::UInt128, y::BigInt) = /(promote(x, y)...)
75+
end
76+
7077
# ensure that the coefficient multiplied by the highest and lowest representable values of
7178
# the container type do not result in overflow.
7279
@testset "coefficient" begin
@@ -436,28 +443,35 @@ end
436443
@test x == round(FD2, x)
437444
end
438445

439-
@testset "limits" begin
440-
for T in CONTAINER_TYPES
441-
f = FixedPointDecimals.max_exp10(T) + 1
442-
@eval begin
443-
powt = FixedPointDecimals.coefficient(FD{$T,$f})
446+
@testset "limits $T" for T in CONTAINER_TYPES
447+
f = FixedPointDecimals.max_exp10(T) + 1
448+
powt = FixedPointDecimals.coefficient(FD{T,f})
444449

445-
max_rounded = round($T, typemax($T) / powt)
446-
min_rounded = round($T, typemin($T) / powt)
450+
# Ideally we would just use `typemax(T)` but due to precision issues with
451+
# floating-point its possible the closest float will exceed `typemax(T)`.
452+
# Additionally, when the division results in a `BigFloat` we need to first truncate
453+
# to a `BigInt` before we can truncate the type we want.
454+
max_int = T(trunc(BigInt, prevfloat(typemax(T) / powt) * powt))
455+
min_int = T(trunc(BigInt, nextfloat(typemin(T) / powt) * powt))
447456

448-
# Note: all values `x` in FD{T,f} are -1 < x < 1
449-
if max_rounded > 0
450-
@test_throws InexactError round(reinterpret(FD{$T,$f}, typemax($T)))
451-
else
452-
@test round(reinterpret(FD{$T,$f}, typemax($T))) == FD{$T,$f}(max_rounded)
453-
end
457+
@test round(FD{T,f}, max_int / powt) == reinterpret(FD{T,f}, max_int)
458+
@test round(FD{T,f}, min_int / powt) == reinterpret(FD{T,f}, min_int)
454459

455-
if min_rounded < 0
456-
@test_throws InexactError round(reinterpret(FD{$T,$f}, typemin($T)))
457-
else
458-
@test round(reinterpret(FD{$T,$f}, typemin($T))) == FD{$T,$f}(min_rounded)
459-
end
460-
end
460+
@test round(FD{T,f}, typemax(T) // powt) == reinterpret(FD{T,f}, typemax(T))
461+
@test round(FD{T,f}, typemin(T) // powt) == reinterpret(FD{T,f}, typemin(T))
462+
463+
# Note: due to the size of `f` all values `x::FD{T,f}` are `-1 < x < 1` which means
464+
# that rounding away from zero will result in an exception.
465+
if round(T, typemax(T) / powt) != 0
466+
@test_throws InexactError round(reinterpret(FD{T,f}, typemax(T)))
467+
else
468+
@test round(reinterpret(FD{T,f}, typemax(T))) == zero(FD{T,f})
469+
end
470+
471+
if round(T, typemin(T) / powt) != 0
472+
@test_throws InexactError round(reinterpret(FD{T,f}, typemin(T)))
473+
else
474+
@test round(reinterpret(FD{T,f}, typemin(T))) == zero(FD{T,f})
461475
end
462476
end
463477
end
@@ -589,15 +603,8 @@ epsi{T}(::Type{T}) = eps(T)
589603
max_int = $T(trunc(BigInt, prevfloat(typemax($T) / powt) * powt))
590604
min_int = $T(trunc(BigInt, nextfloat(typemin($T) / powt) * powt))
591605

592-
# When working with Int128/UInt128 ceil with max_int will fail without this
593-
# Fixed in: https://github.com/JuliaLang/julia/pull/19779
594-
if VERSION < v"0.6"
595-
max_dec = /(promote(max_int, powt)...)
596-
min_dec = /(promote(min_int, powt)...)
597-
else
598-
max_dec = max_int / powt
599-
min_dec = min_dec / powt
600-
end
606+
max_dec = max_int / powt
607+
min_dec = min_int / powt
601608

602609
# Note: Using a larger signed type as the max/min values may be at the
603610
# limits and overflow when adding or subtracting 1.

0 commit comments

Comments
 (0)