@@ -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))
6868end
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
463477end
@@ -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