Skip to content

Commit d2c3fa8

Browse files
committed
added support for an arbitrary number of fraction bits
1 parent 3964895 commit d2c3fa8

File tree

4 files changed

+43
-61
lines changed

4 files changed

+43
-61
lines changed

src/FixedPointNumbers.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,14 @@ scaledual{T<:FixedPoint}(Tdual::Type, x::Union{T,AbstractArray{T}}) =
9090
scaledual{Tdual<:Number, T<:FixedPoint}(b::Tdual, x::Union{T,AbstractArray{T}}) =
9191
convert(Tdual, b/one(T)), reinterpret(rawtype(T), x)
9292

93+
# Show
94+
function show{T<:FixedPoint}(io::IO, x::T)
95+
print(io, typeof(x))
96+
print(io, "(")
97+
showcompact(io, x)
98+
print(io, ")")
99+
end
100+
const _log2_10 = 3.321928094887362
101+
showcompact{T,f}(io::IO, x::UFixed{T,f}) = show(io, round(convert(Float64,x), ceil(Int,f/_log2_10)))
102+
93103
end # module

src/fixed.jl

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,3 @@ promote_rule{T,f,TR}(::Type{Fixed{T,f}}, ::Type{Rational{TR}}) = Rational{TR}
5454

5555
# TODO: Document and check that it still does the right thing.
5656
decompose{T,f}(x::Fixed{T,f}) = x.i, -f, 1
57-
58-
# printing
59-
function show(io::IO, x::Fixed)
60-
print(io, typeof(x))
61-
print(io, "(")
62-
showcompact(io, x)
63-
print(io, ")")
64-
end
65-
const _log2_10 = 3.321928094887362
66-
showcompact{T,f}(io::IO, x::Fixed{T,f}) = show(io, round(convert(Float64,x), ceil(Int,f/_log2_10)))

src/ufixed.jl

Lines changed: 22 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,7 @@ typealias UFixed16 UFixed{UInt16,16}
1919

2020
const UF = (UFixed8, UFixed10, UFixed12, UFixed14, UFixed16)
2121

22-
for (uf) in UF
23-
T = rawtype(uf)
24-
f = nbitsfrac(uf)
25-
@eval reinterpret(::Type{UFixed{$T,$f}}, x::$T) = UFixed{$T,$f}(x, 0)
26-
end
22+
reinterpret{T<:Unsigned, f}(::Type{UFixed{T,f}}, x::T) = UFixed{T,f}(x, 0)
2723

2824
# The next lines mimic the floating-point literal syntax "3.2f0"
2925
immutable UFixedConstructor{T,f} end
@@ -35,14 +31,7 @@ const uf14 = UFixedConstructor{UInt16,14}()
3531
const uf16 = UFixedConstructor{UInt16,16}()
3632

3733
zero{T,f}(::Type{UFixed{T,f}}) = UFixed{T,f}(zero(T),0)
38-
for uf in UF
39-
TT = rawtype(uf)
40-
f = nbitsfrac(uf)
41-
T = UFixed{TT,f}
42-
@eval begin
43-
one(::Type{$T}) = $T($(2^f-1),0)
44-
end
45-
end
34+
one{T<:UFixed}(::Type{T}) = T((2^nbitsfrac(T)-1),0)
4635
zero(x::UFixed) = zero(typeof(x))
4736
one(x::UFixed) = one(typeof(x))
4837
rawone(v) = reinterpret(one(v))
@@ -95,15 +84,21 @@ abs(x::UFixed) = x
9584
# Functions
9685
trunc{T<:UFixed}(x::T) = T(div(reinterpret(x), rawone(T))*rawone(T),0)
9786
floor{T<:UFixed}(x::T) = trunc(x)
98-
for T in UF
99-
f = nbitsfrac(T)
100-
R = rawtype(T)
101-
roundmask = convert(R, 1<<(f-1))
102-
k = 8*sizeof(R)-f
103-
ceilmask = (typemax(R)<<k)>>k
104-
@eval begin
105-
round(x::$T) = (y = trunc(x); return convert(rawtype($T), reinterpret(x)-reinterpret(y))&$roundmask>0 ? $T(y+one($T)) : y)
106-
ceil(x::$T) = (y = trunc(x); return convert(rawtype($T), reinterpret(x)-reinterpret(y))&$ceilmask >0 ? $T(y+one($T)) : y)
87+
@generated function round{T,f}(x::UFixed{T,f})
88+
mask = convert(T, 1<<(f-1))
89+
quote
90+
y = trunc(x)
91+
return convert(T, reinterpret(x)-reinterpret(y)) & $mask>0 ?
92+
UFixed{T,f}(y+one(UFixed{T,f})) : y
93+
end
94+
end
95+
@generated function ceil{T,f}(x::UFixed{T,f})
96+
k = 8*sizeof(T)-f
97+
mask = (typemax(T)<<k)>>k
98+
quote
99+
y = trunc(x)
100+
return convert(T, reinterpret(x)-reinterpret(y)) & ($mask)>0 ?
101+
UFixed{T,f}(y+one(UFixed{T,f})) : y
107102
end
108103
end
109104

@@ -152,25 +147,8 @@ function decompose(x::UFixed)
152147
end
153148

154149
# Promotions
155-
for T in UF
156-
@eval begin
157-
promote_rule(::Type{$T}, ::Type{Float32}) = Float32
158-
promote_rule(::Type{$T}, ::Type{Float64}) = Float64
159-
promote_rule{TR<:Rational}(::Type{$T}, ::Type{TR}) = TR
160-
end
161-
for Ti in (Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64)
162-
Tp = eps(convert(Float32, typemax(Ti))) > eps(T) ? Float64 : Float32
163-
@eval begin
164-
promote_rule(::Type{$T}, ::Type{$Ti}) = $Tp
165-
end
166-
end
167-
end
168-
169-
# Show
170-
function show{T,f}(io::IO, x::UFixed{T,f})
171-
print(io, "UFixed", f)
172-
print(io, "(")
173-
showcompact(io, x)
174-
print(io, ")")
175-
end
176-
showcompact{T,f}(io::IO, x::UFixed{T,f}) = show(io, round(convert(Float64,x), ceil(Int,f/_log2_10)))
150+
promote_rule{T<:UFixed}(::Type{T}, ::Type{Float32}) = Float32
151+
promote_rule{T<:UFixed}(::Type{T}, ::Type{Float64}) = Float64
152+
promote_rule{T<:UFixed, R<:Rational}(::Type{T}, ::Type{R}) = R
153+
promote_rule{T<:UFixed, Ti<:Union{Signed,Unsigned}}(::Type{T}, ::Type{Ti}) =
154+
eps(convert(Float32, typemax(Ti))) > eps(T) ? Float64 : Float32

test/ufixed.jl

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@ using FixedPointNumbers, Base.Test
1717
@test ufixed14(1.0) == 0x3fffuf14
1818
@test ufixed12([2]) == UFixed12[0x1ffeuf12]
1919

20-
for T in FixedPointNumbers.UF
20+
UF2 = (UFixed{UInt32,16}, UFixed{UInt64,3}, UFixed{UInt128,7})
21+
22+
for T in (FixedPointNumbers.UF..., UF2...)
2123
@test zero(T) == 0
2224
@test one(T) == 1
2325
@test one(T) * one(T) == one(T)
2426
@test typemin(T) == 0
2527
@test realmin(T) == 0
2628
@test eps(zero(T)) == eps(typemax(T))
27-
@test sizeof(T) == 1 + (T != UFixed8)
29+
@test sizeof(T) == sizeof(FixedPointNumbers.rawtype(T))
2830
end
2931
@test typemax(UFixed8) == 1
3032
@test typemax(UFixed10) == typemax(UInt16)//(2^10-1)
@@ -34,6 +36,7 @@ end
3436
@test typemax(UFixed10) == typemax(UInt16) // (2^10-1)
3537
@test typemax(UFixed12) == typemax(UInt16) // (2^12-1)
3638
@test typemax(UFixed14) == typemax(UInt16) // (2^14-1)
39+
@test typemax(UFixed{UInt32,16}) == typemax(UInt32) // (2^16-1)
3740

3841
x = UFixed8(0.5)
3942
@test isfinite(x) == true
@@ -45,13 +48,14 @@ x = UFixed8(0.5)
4548
@test convert(UFixed12, 1.1/typemax(UInt16)*16) == eps(UFixed12)
4649
@test convert(UFixed14, 1.1/typemax(UInt16)*4) == eps(UFixed14)
4750
@test convert(UFixed16, 1.1/typemax(UInt16)) == eps(UFixed16)
51+
@test convert(UFixed{UInt32,16}, 1.1/typemax(UInt32)*2^16) == eps(UFixed{UInt32,16})
4852

4953
@test convert(UFixed8, 1.1f0/typemax(UInt8)) == eps(UFixed8)
5054

5155
@test convert(Float64, eps(UFixed8)) == 1/typemax(UInt8)
5256
@test convert(Float32, eps(UFixed8)) == 1.0f0/typemax(UInt8)
5357
@test convert(BigFloat, eps(UFixed8)) == BigFloat(1)/typemax(UInt8)
54-
for T in FixedPointNumbers.UF
58+
for T in (FixedPointNumbers.UF..., UF2...)
5559
@test convert(Bool, zero(T)) == false
5660
@test convert(Bool, one(T)) == true
5761
@test convert(Bool, convert(T, 0.2)) == true
@@ -64,7 +68,7 @@ x = UFixed8(0b01010001, 0)
6468
@test ~x == UFixed8(0b10101110, 0)
6569
@test -x == 0xafuf8
6670

67-
for T in FixedPointNumbers.UF
71+
for T in (FixedPointNumbers.UF..., UF2...)
6872
x = T(0x10,0)
6973
y = T(0x25,0)
7074
fx = convert(Float32, x)
@@ -89,7 +93,7 @@ function testtrunc{T}(inc::T)
8993
incf = convert(Float64, inc)
9094
tm = reinterpret(typemax(T))/reinterpret(one(T))
9195
x = zero(T)
92-
for i = 0:reinterpret(typemax(T))-1
96+
for i = 0 : min(1e6, reinterpret(typemax(T))-1)
9397
xf = incf*i
9498
try
9599
@test trunc(x) == trunc(xf)
@@ -113,7 +117,7 @@ function testtrunc{T}(inc::T)
113117
end
114118
end
115119

116-
for T in FixedPointNumbers.UF
120+
for T in (FixedPointNumbers.UF..., UF2...)
117121
testtrunc(eps(T))
118122
end
119123

@@ -122,7 +126,7 @@ x = 0xaauf8
122126
iob = IOBuffer()
123127
show(iob, x)
124128
str = takebuf_string(iob)
125-
@test startswith(str, "UFixed8(")
129+
@test startswith(str, "FixedPointNumbers.UFixed{UInt8,8}(")
126130
@test eval(parse(str)) == x
127131

128132
# scaledual

0 commit comments

Comments
 (0)