9292# ensure that the coefficient multiplied by the highest and lowest representable values of
9393# the container type do not result in overflow.
9494@testset " coefficient" begin
95- for (i, T) in enumerate (CONTAINER_TYPES)
96- for j in i: length (CONTAINER_TYPES)
97- f = FixedPointDecimals. max_exp10 (CONTAINER_TYPES[j])
98- powt = FixedPointDecimals. coefficient (FD{T, f})
99- @test powt % 10 == 0
100- @test checked_mul (widen (powt), typemax (T)) == widemul (powt, typemax (T))
101- @test checked_mul (widen (powt), typemin (T)) == widemul (powt, typemin (T))
102- end
95+ @testset " overflow $T " for T in CONTAINER_TYPES
96+ f = FixedPointDecimals. max_exp10 (T)
97+ powt = FixedPointDecimals. coefficient (FD{T, f})
98+ @test powt % 10 == 0
99+ @test checked_mul (widen (powt), typemax (T)) == widemul (powt, typemax (T))
100+ @test checked_mul (widen (powt), typemin (T)) == widemul (powt, typemin (T))
103101 end
104102end
105103
143141 end
144142
145143 @testset " limits of $T " for T in CONTAINER_TYPES
146- f = FixedPointDecimals. max_exp10 (T) + 1
147- powt = FixedPointDecimals. coefficient (FD{T,f})
144+ max_exp = FixedPointDecimals. max_exp10 (T)
145+ f = max_exp
146+ powt = widen (FixedPointDecimals. coefficient (FD{T,f}))
147+
148+ # Smallest positive integer which is out-of-bounds for the FD
149+ x = max_exp - f + 1
150+ oob = T (10 )^ (x > 0 ? x : 0 )
148151
149152 # ideally we would just use `typemax(T)` but due to precision issues with
150153 # floating-point its possible the closest float will exceed `typemax(T)`.
161164 @test convert (FD{T,f}, typemax (T) // powt) == reinterpret (FD{T,f}, typemax (T))
162165 @test convert (FD{T,f}, typemin (T) // powt) == reinterpret (FD{T,f}, typemin (T))
163166
164- @test_throws InexactError convert (FD{T,f}, T ( 1 ) )
167+ @test_throws InexactError convert (FD{T,f}, oob )
165168
166169 # Converting to a floating-point
167170 fd = reinterpret (FD{T,f}, typemax (T))
@@ -181,24 +184,21 @@ end
181184 fd = reinterpret (FD{T,f}, typemin (T))
182185 @test convert (Rational, fd) == typemin (T) // powt
183186
184- # Adjust number of decimal places allowed so we can have `-10 < x < 10` where x is
185- # a FD{T,f}. Only needed to test `convert(::FD, ::Integer)`
186- f = FixedPointDecimals. max_exp10 (T)
187- powt = FixedPointDecimals. coefficient (FD{T,f})
188-
187+ # The following tests require that the number of decimal places allow for
188+ # `-10 < x < 10` where x is a FD{T,f}. Needed to test `convert(::FD, ::Integer)`.
189189 max_int = typemax (T) ÷ powt * powt
190190 min_int = typemin (T) ÷ powt * powt
191191
192192 @test convert (FD{T,f}, max_int ÷ powt) == reinterpret (FD{T,f}, max_int)
193193 @test convert (FD{T,f}, min_int ÷ powt) == reinterpret (FD{T,f}, min_int)
194194
195- @test_throws InexactError convert (FD{T,f}, max_int ÷ powt + T ( 1 ) )
196- @test_throws InexactError convert (FD{T,f}, min_int ÷ powt - T ( 1 ) ) # Overflows with Unsigned
195+ @test_throws InexactError convert (FD{T,f}, max_int ÷ powt + oob )
196+ @test_throws InexactError convert (FD{T,f}, min_int ÷ powt - oob ) # Overflows with Unsigned
197197 end
198198
199199 @testset " limits from $U to $T " for T in CONTAINER_TYPES, U in CONTAINER_TYPES
200- f = FixedPointDecimals. max_exp10 (T) + 1
201- g = FixedPointDecimals. max_exp10 (U) + 1
200+ f = FixedPointDecimals. max_exp10 (T)
201+ g = FixedPointDecimals. max_exp10 (U)
202202 powt = div (
203203 FixedPointDecimals. coefficient (FD{T, f}),
204204 FixedPointDecimals. coefficient (FD{U, g}),
329329 end
330330
331331 @testset " limits of $T " for T in CONTAINER_TYPES
332- x = FixedPointDecimals. max_exp10 (T)
333- f = x + 1
334-
335- scalar = reinterpret (FD{T,f}, T (10 )^ x) # 0.1
332+ f = FixedPointDecimals. max_exp10 (T)
333+ scalar = convert (FD{T,f}, 1 // 10 ) # 0.1
336334
337335 # Since multiply will round the result we'll make sure our value does not
338336 # always rounds down.
@@ -445,10 +443,13 @@ end
445443 end
446444
447445 @testset " limits of $T " for T in CONTAINER_TYPES
448- x = FixedPointDecimals. max_exp10 (T)
449- f = x + 1
446+ max_exp = FixedPointDecimals. max_exp10 (T)
447+ f = max_exp
448+ scalar = convert (FD{T,f}, 1 // 10 ) # 0.1
450449
451- scalar = reinterpret (FD{T,f}, T (10 )^ x) # 0.1
450+ # Should be outside of the bounds of a FD{T,f}
451+ x = T (10 )
452+ @test_throws InexactError FD {T,f} (x)
452453
453454 # Since multiply will round the result we'll make sure our value always
454455 # rounds down.
459460
460461 @test (max_fd * scalar) / scalar == max_fd
461462 @test (min_fd * scalar) / scalar == min_fd
462- @test max_fd / T (2 ) == reinterpret (FD{T,f}, div (max_int, 2 ))
463- @test min_fd / T (2 ) == reinterpret (FD{T,f}, div (min_int, 2 ))
464-
465- # Since the precision of `f` doesn't allow us to make a FixedDecimal >= 1
466- # there is no way testing this function without raising an exception.
467- max_fd != 0 && @test_throws InexactError T (2 ) / max_fd
468- min_fd != 0 && @test_throws InexactError T (2 ) / min_fd
463+ @test max_fd / x == reinterpret (FD{T,f}, div (max_int, x))
464+ @test min_fd / x == reinterpret (FD{T,f}, div (min_int, x))
469465 end
470466end
471467
@@ -486,10 +482,11 @@ end
486482end
487483
488484@testset " isinteger" begin
489- @testset " overflow" begin
490- # Note: After overflow `Int8(10)^6 == 64`
491- @test ! isinteger (reinterpret (FD{Int8,6 }, 64 )) # 0.000064
492- end
485+ # Note: Test cannot be used unless we can construct `FD{Int8,6}`
486+ # @testset "overflow" begin
487+ # # Note: After overflow `Int8(10)^6 == 64`
488+ # @test !isinteger(reinterpret(FD{Int8,6}, 64)) # 0.000064
489+ # end
493490
494491 @testset " limits of $T " for T in CONTAINER_TYPES
495492 f = FixedPointDecimals. max_exp10 (T)
531528 end
532529
533530 @testset " limits of $T " for T in CONTAINER_TYPES
534- f = FixedPointDecimals. max_exp10 (T) + 1
531+ f = FixedPointDecimals. max_exp10 (T)
535532 powt = FixedPointDecimals. coefficient (FD{T,f})
536533
537534 # Ideally we would just use `typemax(T)` but due to precision issues with
@@ -547,18 +544,23 @@ end
547544 @test round (FD{T,f}, typemax (T) // powt) == reinterpret (FD{T,f}, typemax (T))
548545 @test round (FD{T,f}, typemin (T) // powt) == reinterpret (FD{T,f}, typemin (T))
549546
550- # Note: due to the size of `f` all values `x::FD{T,f}` are `-1 < x < 1` which means
551- # that rounding away from zero will result in an exception.
552- if round (T, typemax (T) / powt) != 0
553- @test_throws InexactError round (reinterpret (FD{T,f}, typemax (T)))
547+ # Note: rounding away from zero will result in an exception.
548+ max_int = typemax (T)
549+ min_int = typemin (T)
550+
551+ max_dec = max_int / powt
552+ min_dec = min_int / powt
553+
554+ if round (T, max_dec) == trunc (T, max_dec)
555+ @test round (reinterpret (FD{T,f}, max_int)) == FD {T,f} (round (T, max_dec))
554556 else
555- @test round (reinterpret (FD{T,f}, typemax (T))) == zero (FD{T,f} )
557+ @test_throws InexactError round (reinterpret (FD{T,f}, max_int) )
556558 end
557559
558- if round (T, typemin (T) / powt) != 0
559- @test_throws InexactError round (reinterpret (FD{T,f}, typemin (T) ))
560+ if round (T, min_dec) == trunc (T, min_dec)
561+ @test round (reinterpret (FD{T,f}, min_int)) == FD {T,f} ( round (T, min_dec ))
560562 else
561- @test round (reinterpret (FD{T,f}, typemin (T))) == zero (FD{T,f} )
563+ @test_throws InexactError round (reinterpret (FD{T,f}, min_int) )
562564 end
563565 end
564566end
608610 end
609611
610612 @testset " limits of $T " for T in CONTAINER_TYPES
611- f = FixedPointDecimals. max_exp10 (T) + 1
613+ f = FixedPointDecimals. max_exp10 (T)
612614 powt = FixedPointDecimals. coefficient (FD{T,f})
613615
614616 # Ideally we would just use `typemax(T)` but due to precision issues with
624626 @test value (trunc (FD{T,f}, max_int / powt)) in [max_int, max_int - 1 ]
625627 @test value (trunc (FD{T,f}, min_int / powt)) in [min_int, min_int + 1 ]
626628
627- # Note: all values `x` in FD{T,f} are -1 < x < 1
628- @test trunc (reinterpret (FD{T,f}, typemax (T))) == zero (FD{T,f})
629- @test trunc (reinterpret (FD{T,f}, typemin (T))) == zero (FD{T,f})
629+ @test trunc (reinterpret (FD{T,f}, typemax (T))) == FD {T,f} (div (typemax (T), powt))
630+ @test trunc (reinterpret (FD{T,f}, typemin (T))) == FD {T,f} (div (typemin (T), powt))
630631 end
631632end
632633
@@ -674,7 +675,7 @@ epsi{T}(::Type{T}) = eps(T)
674675 end
675676
676677 @testset " limits of $T " for T in CONTAINER_TYPES
677- f = FixedPointDecimals. max_exp10 (T) + 1
678+ f = FixedPointDecimals. max_exp10 (T)
678679 powt = FixedPointDecimals. coefficient (FD{T,f})
679680
680681 # Ideally we would just use `typemax(T)` but due to precision issues with
@@ -695,16 +696,26 @@ epsi{T}(::Type{T}) = eps(T)
695696 @test value (ceil (FD{T,f}, max_dec)) in [max_int, signed (widen (max_int)) + 1 ]
696697 @test value (ceil (FD{T,f}, min_dec)) in [min_int, min_int + 1 ]
697698
698- # Note: all values `x` in FD{T,f} are -1 < x < 1
699- @test floor (reinterpret (FD{T,f}, typemax (T))) == zero (FD{T,f})
700- if T <: Unsigned
701- @test floor (reinterpret (FD{T,f}, typemin (T))) == zero (FD{T,f})
699+ # Note: rounding away from zero will result in an exception.
700+ max_int = typemax (T)
701+ min_int = typemin (T)
702+
703+ max_dec = max_int / powt
704+ min_dec = min_int / powt
705+
706+ @test floor (reinterpret (FD{T,f}, max_int)) == FD {T,f} (floor (T, max_dec))
707+ if floor (T, min_dec) == trunc (T, min_dec)
708+ @test floor (reinterpret (FD{T,f}, min_int)) == FD {T,f} (floor (T, min_dec))
702709 else
703- @test_throws InexactError floor (reinterpret (FD{T,f}, typemin (T) ))
710+ @test_throws InexactError floor (reinterpret (FD{T,f}, min_int ))
704711 end
705712
706- @test_throws InexactError ceil (reinterpret (FD{T,f}, typemax (T)))
707- @test ceil (reinterpret (FD{T,f}, typemin (T))) == zero (FD{T,f})
713+ if ceil (T, max_dec) == trunc (T, max_dec)
714+ @test ceil (reinterpret (FD{T,f}, max_int)) == FD {T,f} (ceil (T, max_dec))
715+ else
716+ @test_throws InexactError ceil (reinterpret (FD{T,f}, max_int))
717+ end
718+ @test ceil (reinterpret (FD{T,f}, min_int)) == FD {T,f} (ceil (T, min_dec))
708719 end
709720end
710721
@@ -720,12 +731,20 @@ end
720731 # Displaying a decimal could be incorrect when using a decimal place precision which is
721732 # close to or at the limit for our storage type.
722733 @testset " limits of $T " for T in CONTAINER_TYPES
723- f = FixedPointDecimals. max_exp10 (T) + 1
724- max_str = " 0." * rpad (typemax (T), f, ' 0' )
725- min_str = (typemin (T) < 0 ? " -" : " " ) * " 0." * rpad (abs (widen (typemin (T))), f, ' 0' )
734+ f = FixedPointDecimals. max_exp10 (T)
735+
736+ function fmt (val, f)
737+ str = string (val)
738+ neg = " "
739+ if str[1 ] == ' -'
740+ neg = " -"
741+ str = str[2 : end ]
742+ end
743+ return string (neg, str[1 ], " ." , rpad (str[2 : end ], f, ' 0' ))
744+ end
726745
727- @test string (reinterpret (FD{T,f}, typemax (T))) == max_str
728- @test string (reinterpret (FD{T,f}, typemin (T))) == min_str
746+ @test string (reinterpret (FD{T,f}, typemax (T))) == fmt ( typemax (T), f)
747+ @test string (reinterpret (FD{T,f}, typemin (T))) == fmt ( typemin (T), f)
729748 end
730749end
731750
0 commit comments