I’d like to better understand what is possible to do in the where clause of a typed function.
In my case, I’m trying to enhance fixed-point arithmetics for a project that verifies an algorithm to be implemented on an embedded HW in fixed point arithmetics.
is it possible to define a promote rule for addition to take the fixed-point with greater “precision” (amount of decimal places) like this (do some arithmetics in the where clause) ?
promote_rule(::Type{Fixed{T,f1}}, ::Type{Fixed{T,f2}}) where {T<:Signed, f1, f2} where f1>f2 = Fixed{T,f1}
promote_rule(::Type{Fixed{T,f1}}, ::Type{Fixed{T,f2}}) where {T<:Signed, f1, f2} where f1<f2 = Fixed{T,f2}
This syntax errors with “error in where statement”. What works correctly - but produces a very slow code (1000x degradation) is
promote_rule(::Type{Fixed{T,f1}}, ::Type{Fixed{T,f2}}) where {T<:Signed, f1, f2} = Fixed{T,f1>f2?f1:f2}
If I try it with “hardcoded” not correct version that works only for f2 > f1 (but produces always the same type result)
promote_rule(::Type{Fixed{T,f1}}, ::Type{Fixed{T,f2}}) where {T<:Signed, f1, f2} = Fixed{T,f2}
it runs on full speed!
The full code snippet to test the problem:
julia> using BenchmarkTools
julia> using FixedPointNumbers
julia> import Base.convert
julia> import Base.promote_rule
julia> convert(::Type{TF}, x::Fixed{T2,f2}) where {TF <: Fixed{T1,f1},T2, f2} where {T1, f1} = Fixed{T1, f1}(x.i>>(f2-f1), 0)
julia> promote_rule(::Type{Fixed{T,f1}}, ::Type{Fixed{T,f2}}) where {T<:Signed,f1, f2} = Fixed{T,f1>f2?f1:f2}
julia> function benchmark(x,y)
z = x
for i = 1:1000
z += i + x+y
end
z
end
julia> a1 = convert(Fixed{Int64, 12}, 1.0)
julia> b1 = convert(Fixed{Int64, 20}, 2.0)
julia> a2 = 1.0
julia> b2 = 2.0
julia> @btime benchmark(a1,b1)
4.627 ms (30029 allocations: 1.31 MiB)
503501.0Q43f20
julia> @btime benchmark(a2,b2)
1.313 μs (1 allocation: 16 bytes)
503501.0