|
| 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