Skip to content

Commit 40c9117

Browse files
authored
Systemize fixed point types to be tested (#208)
This abstracts the selection of the types to be tested and makes it more systematic. As a result, we can reduce impractical test cases (e.g. for the 128-bit types) without significantly compromising the test quality. This also reorders some test sets.
2 parents 33f2583 + 837bc9c commit 40c9117

File tree

4 files changed

+571
-463
lines changed

4 files changed

+571
-463
lines changed

test/common.jl

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
using FixedPointNumbers, Statistics, Test
2+
using FixedPointNumbers: bitwidth, rawtype, nbitsfrac
3+
4+
"""
5+
target(X::Type, Ss...; ex = :default)
6+
7+
Return a generator which enumerates the target types for testing.
8+
9+
# Arguments
10+
- `X`: target base type
11+
- `Ss`: symbols for specifying the target raw types
12+
- `:i*` : a `Signed` type if `X === Fixed`, or an `Unsigned` type if `X === Normed`
13+
- `:s*` : a `Signed` type (not yet supported)
14+
- `:u*` : an `Unsigned` type (not yet supported)
15+
- `ex`: exhaustivity of `f`s (see also the [`target_f`](@ref) function)
16+
- `:heavy`: all supported `f`s
17+
- `:default`: same as `:heavy` for 8-/16-bit types, and same as `:light` otherwise
18+
- `:light`: important `f`s for byte boundaries and floating point types
19+
- `:thin`: maximum and half `f`s per type
20+
21+
# Example
22+
```julia
23+
julia> collect(target(Normed, :i8, :i32; ex = :default))
24+
21-element Array{DataType,1}:
25+
Normed{UInt8,1}
26+
Normed{UInt8,2}
27+
Normed{UInt8,3}
28+
Normed{UInt8,4}
29+
Normed{UInt8,5}
30+
Normed{UInt8,6}
31+
Normed{UInt8,7}
32+
Normed{UInt8,8}
33+
Normed{UInt32,1}
34+
Normed{UInt32,7}
35+
Normed{UInt32,8}
36+
Normed{UInt32,9}
37+
Normed{UInt32,10}
38+
Normed{UInt32,11}
39+
Normed{UInt32,15}
40+
Normed{UInt32,16}
41+
Normed{UInt32,17}
42+
Normed{UInt32,23}
43+
Normed{UInt32,24}
44+
Normed{UInt32,31}
45+
Normed{UInt32,32}
46+
```
47+
"""
48+
function target(X::Type, Ss...; ex = :default)
49+
Ts = symbol_to_inttype.(X, Ss)
50+
(X{T,f} for T in Ts for f in target_f(X, T; ex = ex))
51+
end
52+
target(X::Type; ex = :default) = target(X, :i8, :i16, :i32, :i64, :i128; ex = ex)
53+
54+
"""
55+
target_f(X::Type, T::Type; ex = :default)
56+
57+
Return a tuple or range of the number of fractional bits `f` to be tested.
58+
59+
# Arguments
60+
The `X` specifies the target base type, i.e. `Fixed` or `Normed`, and the `T`
61+
specifies the target raw type.
62+
63+
## `ex` keyword
64+
The `ex` specifies the exhaustivity of `f`s.
65+
The following are examples of `target_f(Normed, T)`. The marker `x` means the
66+
target and the marker `-` means not the target.
67+
68+
### `:heavy` -- all supported `f`s
69+
```
70+
| 3 2 1 |
71+
f |2 1 0 9 8 7 6 5:4 3 2 1 0 9 8 7:6 5 4 3 2 1 0 9:8 7 6 5 4 3 2 1|
72+
T == UInt8 | : : :x x x x x x x x|
73+
T == UInt16 | : :x x x x x x x x:x x x x x x x x|
74+
T == UInt32 |x x x x x x x x:x x x x x x x x:x x x x x x x x:x x x x x x x x|
75+
```
76+
### `:default` -- same as `:heavy` for 8-/16-bit types, and same as `:light` otherwise
77+
```
78+
| 3 2 1 |
79+
f |2 1 0 9 8 7 6 5:4 3 2 1 0 9 8 7:6 5 4 3 2 1 0 9:8 7 6 5 4 3 2 1|
80+
T == UInt8 | : : :x x x x x x x x|
81+
T == UInt16 | : :x x x x x x x x:x x x x x x x x|
82+
T == UInt32 |x x - - - - - -:x x - - - - - x:x x - - - x x x:x x - - - - - x|
83+
```
84+
85+
### `:light` -- important `f`s for byte boundaries and floating point types
86+
```
87+
| 3 2 1 |
88+
f |2 1 0 9 8 7 6 5:4 3 2 1 0 9 8 7:6 5 4 3 2 1 0 9:8 7 6 5 4 3 2 1|
89+
T == UInt8 | : : :x x - - - - - x|
90+
T == UInt16 | : :x x - - - x x x:x x - - - - - x|
91+
T == UInt32 |x x - - - - - -:x x - - - - - x:x x - - - x x x:x x - - - - - x|
92+
| |
93+
+--precision(Float32) +--precision(Float16)
94+
```
95+
96+
### `:thin` -- maximum and half `f`s per type
97+
```
98+
| 3 2 1 |
99+
f |2 1 0 9 8 7 6 5:4 3 2 1 0 9 8 7:6 5 4 3 2 1 0 9:8 7 6 5 4 3 2 1|
100+
T == UInt8 | : : :x - - - x - - -|
101+
T == UInt16 | : :x - - - - - - -:x - - - - - - -|
102+
T == UInt32 |x - - - - - - -:- - - - - - - -:x - - - - - - -:- - - - - - - -|
103+
```
104+
"""
105+
function target_f(X::Type, T::Type{<:Integer}; ex = :default)
106+
f_min = X === Fixed ? 0 : 1
107+
f_max = bitwidth(T) - (T <: Signed) - 1 + f_min
108+
ex === :heavy && return f_min:f_max
109+
ex === :default && bitwidth(T) <= 16 && return f_min:f_max
110+
ex === :thin && return ((f_max + 1) ÷ 2, f_max)
111+
if ex === :light || ex === :default
112+
itr = Iterators.filter(x -> x <= f_max, target_f_series(X, T))
113+
return (itr...,)
114+
end
115+
error()
116+
end
117+
118+
target_f_series(::Type{Fixed}, T::Type{<:Integer}) =
119+
(0, 1, 7, 8, 9,
120+
10, 11, 15, 16, 17,
121+
23, 24, 31, 32, 33,
122+
52, 53, 63, 64, 65,
123+
112, 113, 127)
124+
125+
target_f_series(::Type{Normed}, T::Type{<:Integer}) =
126+
(1, 7, 8, 9,
127+
10, 11, 15, 16, 17,
128+
23, 24, 31, 32, 33,
129+
52, 53, 63, 64, 65,
130+
112, 113, 127, 128)

0 commit comments

Comments
 (0)