Skip to content

Commit 39d4687

Browse files
committed
implement promotion between Fixed types
1 parent 261630f commit 39d4687

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

src/FixedPointNumbers.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ widen1(::Type{Int32}) = Int64
6969
widen1(::Type{UInt32}) = UInt64
7070
widen1(::Type{Int64}) = Int128
7171
widen1(::Type{UInt64}) = UInt128
72+
widen1(::Type{Int128}) = Int128
7273
widen1(::Type{UInt128}) = UInt128
7374
widen1(x::Integer) = x % widen1(typeof(x))
7475

src/fixed.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ abs(x::Fixed{T,f}) where {T,f} = Fixed{T,f}(abs(x.i),0)
4545

4646

4747
# # conversions and promotions
48+
function Fixed{T,f}(x::Fixed{T2,f2}) where {T <: Integer,T2 <: Integer,f,f2}
49+
# reinterpret(Fixed{T,f},T(reinterpret(x)<<(f-f2)))
50+
U = Fixed{T,f}
51+
y = round(((1<<f)/(1<<f2))*reinterpret(x))
52+
(typemin(T) <= y) & (y <= typemax(T)) || throw_converterror(U, x)
53+
reinterpret(U, _unsafe_trunc(T, y))
54+
end
4855

4956
rem(x::Integer, ::Type{Fixed{T,f}}) where {T,f} = Fixed{T,f}(rem(x,T)<<f,0)
5057
rem(x::Real, ::Type{Fixed{T,f}}) where {T,f} = Fixed{T,f}(rem(Integer(trunc(x)),T)<<f + rem(Integer(round(rem(x,1)*(one(widen1(T))<<f))),T),0)
@@ -73,5 +80,20 @@ promote_rule(ft::Type{Fixed{T,f}}, ::Type{TI}) where {T,f,TI <: Integer} = Fixed
7380
promote_rule(::Type{Fixed{T,f}}, ::Type{TF}) where {T,f,TF <: AbstractFloat} = TF
7481
promote_rule(::Type{Fixed{T,f}}, ::Type{Rational{TR}}) where {T,f,TR} = Rational{TR}
7582

83+
@generated function promote_rule(::Type{Fixed{T1,f1}}, ::Type{Fixed{T2,f2}}) where {T1,T2,f1,f2}
84+
f = max(f1, f2) # ensure we have enough precision
85+
T = promote_type(T1, T2)
86+
# make sure we have enough integer bits
87+
i1, i2 = 8*sizeof(T1)-f1, 8*sizeof(T2)-f2 # number of integer bits for each
88+
i = 8*sizeof(T)-f
89+
while i < max(i1, i2)
90+
Tw = widen1(T)
91+
T == Tw && break
92+
T = Tw
93+
i = 8*sizeof(T)-f
94+
end
95+
:(Fixed{$T,$f})
96+
end
97+
7698
# TODO: Document and check that it still does the right thing.
7799
decompose(x::Fixed{T,f}) where {T,f} = x.i, -f, 1

test/fixed.jl

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function test_fixed(::Type{T}, f) where {T}
1616
if !(typemin(T) < x <= typemax(T))
1717
continue
1818
end
19-
isinteger(x) && @show x
19+
# isinteger(x) && @show x
2020
fx = convert(T,x)
2121
@test convert(T,convert(Float64, fx)) == fx
2222
@test convert(T,convert(Float64, -fx)) == -fx
@@ -62,7 +62,7 @@ end
6262
@testset "test_fixed" begin
6363
for (TI, f) in [(Int8, 8), (Int16, 8), (Int16, 10), (Int32, 16)]
6464
T = Fixed{TI,f}
65-
println(" Testing $T")
65+
# println(" Testing $T")
6666
test_fixed(T, f)
6767
end
6868
end
@@ -166,4 +166,30 @@ for (T, f) in ((Int8, 7),
166166
@test abs(Fixed{T, f}(x) - x) <= tol
167167
end
168168
end
169+
170+
@testset "Promotion within Fixed" begin
171+
@test @inferred(promote(Q0f7(0.25), Q0f7(0.75))) ===
172+
(Q0f7(0.25), Q0f7(0.75))
173+
@test @inferred(promote(Fixed{Int16,3}(0.25), Fixed{Int8,3}(0.875))) ===
174+
(Fixed{Int16,3}(0.25), Fixed{Int16,3}(0.875))
175+
@test @inferred(promote(Fixed{Int8,6}(0.125), Fixed{Int8,4}(0.75))) ===
176+
(Fixed{Int16,6}(0.125), Fixed{Int16,6}(0.75))
177+
178+
@test Fixed{Int16,15}(-1) == Fixed{Int8,7}(-1)
179+
@test Fixed{Int16,15}(0.25) == Fixed{Int8,7}(0.25)
180+
@test Fixed{Int16,7}(-1) == Fixed{Int8,7}(-1)
181+
@test Fixed{Int16,7}(0.25) == Fixed{Int8,7}(0.25)
182+
@test Fixed{Int16,15}(-1) == Fixed{Int8,5}(-1)
183+
@test Fixed{Int16,15}(5/32) == Fixed{Int8,5}(5/32)
184+
@test Fixed{Int16,3}(-1) == Fixed{Int8,5}(-1)
185+
@test Fixed{Int16,3}(0.25) == Fixed{Int8,5}(0.25)
186+
187+
@test promote_type(Q0f7,Float32,Int) == Float32
188+
@test promote_type(Q0f7,Int,Float32) == Float32
189+
@test promote_type(Int,Q0f7,Float32) == Float32
190+
@test promote_type(Int,Float32,Q0f7) == Float32
191+
@test promote_type(Float32,Int,Q0f7) == Float32
192+
@test promote_type(Float32,Q0f7,Int) == Float32
193+
@test promote_type(Q0f7,Q1f6,Q2f5,Q3f4,Q4f3,Q5f2) == Fixed{Int128,7}
194+
end
169195
end

0 commit comments

Comments
 (0)