Skip to content

Commit d15e2dc

Browse files
committed
Fix trunc, floor, and ceil at the input limits
1 parent 2633540 commit d15e2dc

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

src/FixedPointDecimals.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ for fn in [:trunc, :floor, :ceil]
185185
# round/trunc/ceil/flooring to FD; generic
186186
# TODO. we may need to check overflow and boundary conditions here.
187187
@eval function $fn{T, f}(::Type{FD{T, f}}, x::Real)
188-
powt = T(10)^f
188+
powt = coefficient(FD{T, f})
189189
val = trunc(T, $(Symbol(fn, "mul"))(x, powt))
190190
reinterpret(FD{T, f}, val)
191191
end

test/runtests.jl

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,25 @@ end
404404
end
405405
end
406406
end
407+
408+
@testset "limits" begin
409+
for T in CONTAINER_TYPES
410+
f = FixedPointDecimals.max_exp10(T) + 1
411+
@eval begin
412+
powt = FixedPointDecimals.coefficient(FD{$T,$f})
413+
414+
# ideally we would just use `typemax(T)` but due to precision issues with
415+
# floating-point its possible the closest float will exceed `typemax(T)`.
416+
max_int = trunc(BigInt, prevfloat(typemax($T) / powt) * powt)
417+
min_int = trunc(BigInt, nextfloat(typemin($T) / powt) * powt)
418+
419+
# Do not need to know the exact value as we're primarily looking for
420+
# issues relating to overflow
421+
@test trunc(FD{$T,$f}, max_int / powt).i in (max_int, max_int - 1)
422+
@test trunc(FD{$T,$f}, min_int / powt).i in (min_int, min_int + 1)
423+
end
424+
end
425+
end
407426
end
408427

409428
# eps that works for integers too
@@ -448,6 +467,30 @@ epsi{T}(::Type{T}) = eps(T)
448467
@test floor(FD3, x) == floor(FD4, x) == FD4(x)
449468
end
450469
end
470+
471+
@testset "limits" begin
472+
for T in CONTAINER_TYPES
473+
f = FixedPointDecimals.max_exp10(T) + 1
474+
@eval begin
475+
powt = FixedPointDecimals.coefficient(FD{$T,$f})
476+
477+
# ideally we would just use `typemax(T)` but due to precision issues with
478+
# floating-point its possible the closest float will exceed `typemax(T)`.
479+
# Using BigInt as this will avoid overflowing when we do `max_int + 1` and
480+
# `min_int - 1`.
481+
max_int = trunc(BigInt, prevfloat(typemax($T) / powt) * powt)
482+
min_int = trunc(BigInt, nextfloat(typemin($T) / powt) * powt)
483+
484+
# Do not need to know the exact value as we're primarily looking for
485+
# issues relating to overflow
486+
@test floor(FD{$T,$f}, max_int / powt).i in (max_int, max_int - 1)
487+
@test floor(FD{$T,$f}, min_int / powt).i in (min_int, min_int - 1)
488+
489+
@test ceil(FD{$T,$f}, max_int / powt).i in (max_int, max_int + 1)
490+
@test ceil(FD{$T,$f}, min_int / powt).i in (min_int, min_int + 1)
491+
end
492+
end
493+
end
451494
end
452495

453496
@testset "print" begin

0 commit comments

Comments
 (0)