92
92
# ensure that the coefficient multiplied by the highest and lowest representable values of
93
93
# the container type do not result in overflow.
94
94
@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))
103
101
end
104
102
end
105
103
143
141
end
144
142
145
143
@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 )
148
151
149
152
# ideally we would just use `typemax(T)` but due to precision issues with
150
153
# floating-point its possible the closest float will exceed `typemax(T)`.
161
164
@test convert (FD{T,f}, typemax (T) // powt) == reinterpret (FD{T,f}, typemax (T))
162
165
@test convert (FD{T,f}, typemin (T) // powt) == reinterpret (FD{T,f}, typemin (T))
163
166
164
- @test_throws InexactError convert (FD{T,f}, T ( 1 ) )
167
+ @test_throws InexactError convert (FD{T,f}, oob )
165
168
166
169
# Converting to a floating-point
167
170
fd = reinterpret (FD{T,f}, typemax (T))
@@ -181,24 +184,21 @@ end
181
184
fd = reinterpret (FD{T,f}, typemin (T))
182
185
@test convert (Rational, fd) == typemin (T) // powt
183
186
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)`.
189
189
max_int = typemax (T) ÷ powt * powt
190
190
min_int = typemin (T) ÷ powt * powt
191
191
192
192
@test convert (FD{T,f}, max_int ÷ powt) == reinterpret (FD{T,f}, max_int)
193
193
@test convert (FD{T,f}, min_int ÷ powt) == reinterpret (FD{T,f}, min_int)
194
194
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
197
197
end
198
198
199
199
@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)
202
202
powt = div (
203
203
FixedPointDecimals. coefficient (FD{T, f}),
204
204
FixedPointDecimals. coefficient (FD{U, g}),
329
329
end
330
330
331
331
@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
336
334
337
335
# Since multiply will round the result we'll make sure our value does not
338
336
# always rounds down.
@@ -445,10 +443,13 @@ end
445
443
end
446
444
447
445
@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
450
449
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)
452
453
453
454
# Since multiply will round the result we'll make sure our value always
454
455
# rounds down.
459
460
460
461
@test (max_fd * scalar) / scalar == max_fd
461
462
@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))
469
465
end
470
466
end
471
467
@@ -486,10 +482,11 @@ end
486
482
end
487
483
488
484
@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
493
490
494
491
@testset " limits of $T " for T in CONTAINER_TYPES
495
492
f = FixedPointDecimals. max_exp10 (T)
531
528
end
532
529
533
530
@testset " limits of $T " for T in CONTAINER_TYPES
534
- f = FixedPointDecimals. max_exp10 (T) + 1
531
+ f = FixedPointDecimals. max_exp10 (T)
535
532
powt = FixedPointDecimals. coefficient (FD{T,f})
536
533
537
534
# Ideally we would just use `typemax(T)` but due to precision issues with
@@ -547,18 +544,23 @@ end
547
544
@test round (FD{T,f}, typemax (T) // powt) == reinterpret (FD{T,f}, typemax (T))
548
545
@test round (FD{T,f}, typemin (T) // powt) == reinterpret (FD{T,f}, typemin (T))
549
546
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))
554
556
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) )
556
558
end
557
559
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 ))
560
562
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) )
562
564
end
563
565
end
564
566
end
608
610
end
609
611
610
612
@testset " limits of $T " for T in CONTAINER_TYPES
611
- f = FixedPointDecimals. max_exp10 (T) + 1
613
+ f = FixedPointDecimals. max_exp10 (T)
612
614
powt = FixedPointDecimals. coefficient (FD{T,f})
613
615
614
616
# Ideally we would just use `typemax(T)` but due to precision issues with
624
626
@test value (trunc (FD{T,f}, max_int / powt)) in [max_int, max_int - 1 ]
625
627
@test value (trunc (FD{T,f}, min_int / powt)) in [min_int, min_int + 1 ]
626
628
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))
630
631
end
631
632
end
632
633
@@ -674,7 +675,7 @@ epsi{T}(::Type{T}) = eps(T)
674
675
end
675
676
676
677
@testset " limits of $T " for T in CONTAINER_TYPES
677
- f = FixedPointDecimals. max_exp10 (T) + 1
678
+ f = FixedPointDecimals. max_exp10 (T)
678
679
powt = FixedPointDecimals. coefficient (FD{T,f})
679
680
680
681
# Ideally we would just use `typemax(T)` but due to precision issues with
@@ -695,16 +696,26 @@ epsi{T}(::Type{T}) = eps(T)
695
696
@test value (ceil (FD{T,f}, max_dec)) in [max_int, signed (widen (max_int)) + 1 ]
696
697
@test value (ceil (FD{T,f}, min_dec)) in [min_int, min_int + 1 ]
697
698
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))
702
709
else
703
- @test_throws InexactError floor (reinterpret (FD{T,f}, typemin (T) ))
710
+ @test_throws InexactError floor (reinterpret (FD{T,f}, min_int ))
704
711
end
705
712
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))
708
719
end
709
720
end
710
721
@@ -720,12 +731,20 @@ end
720
731
# Displaying a decimal could be incorrect when using a decimal place precision which is
721
732
# close to or at the limit for our storage type.
722
733
@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
726
745
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)
729
748
end
730
749
end
731
750
0 commit comments