@@ -67,6 +67,13 @@ function parse_int{T, f}(::Type{FD{T, f}}, val::AbstractString; ceil::Bool=false
67
67
reinterpret (FD{T, f}, parse (T, val[1 : (f + 1 )]) + T (ceil))
68
68
end
69
69
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
+
70
77
# ensure that the coefficient multiplied by the highest and lowest representable values of
71
78
# the container type do not result in overflow.
72
79
@testset " coefficient" begin
@@ -436,28 +443,35 @@ end
436
443
@test x == round (FD2, x)
437
444
end
438
445
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})
444
449
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))
447
456
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)
454
459
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})
461
475
end
462
476
end
463
477
end
@@ -589,15 +603,8 @@ epsi{T}(::Type{T}) = eps(T)
589
603
max_int = $ T (trunc (BigInt, prevfloat (typemax ($ T) / powt) * powt))
590
604
min_int = $ T (trunc (BigInt, nextfloat (typemin ($ T) / powt) * powt))
591
605
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
601
608
602
609
# Note: Using a larger signed type as the max/min values may be at the
603
610
# limits and overflow when adding or subtracting 1.
0 commit comments