|
| 1 | +# 32-bit fixed point; parameter `f` is the number of fraction bits |
| 2 | +immutable Fixed{T <: Signed,f} <: FixedPoint{T, f} |
| 3 | + i::T |
| 4 | + |
| 5 | + # constructor for manipulating the representation; |
| 6 | + # selected by passing an extra dummy argument |
| 7 | + Fixed(i::Integer,_) = new(i % T) |
| 8 | + |
| 9 | + Fixed(x) = convert(Fixed{T,f}, x) |
| 10 | +end |
| 11 | + |
| 12 | +typealias Fixed16 Fixed{Int32, 16} |
| 13 | + |
| 14 | + rawtype{T,f}(::Type{Fixed{T,f}}) = T |
| 15 | +nbitsfrac{T,f}(::Type{Fixed{T,f}}) = f |
| 16 | + |
| 17 | +# basic operators |
| 18 | +-{T,f}(x::Fixed{T,f}) = Fixed{T,f}(-x.i,0) |
| 19 | +abs{T,f}(x::Fixed{T,f}) = Fixed{T,f}(abs(x.i),0) |
| 20 | + |
| 21 | ++{T,f}(x::Fixed{T,f}, y::Fixed{T,f}) = Fixed{T,f}(x.i+y.i,0) |
| 22 | +-{T,f}(x::Fixed{T,f}, y::Fixed{T,f}) = Fixed{T,f}(x.i-y.i,0) |
| 23 | + |
| 24 | +# with truncation: |
| 25 | +#*{f}(x::Fixed32{f}, y::Fixed32{f}) = Fixed32{f}(Base.widemul(x.i,y.i)>>f,0) |
| 26 | +# with rounding up: |
| 27 | +*{T,f}(x::Fixed{T,f}, y::Fixed{T,f}) = Fixed{T,f}((Base.widemul(x.i,y.i) + (convert(widen(T), 1) << (f-1) ))>>f,0) |
| 28 | + |
| 29 | +/{T,f}(x::Fixed{T,f}, y::Fixed{T,f}) = Fixed{T,f}(div(convert(widen(T), x.i) << f, y.i), 0) |
| 30 | + |
| 31 | + |
| 32 | +# # conversions and promotions |
| 33 | +convert{T,f}(::Type{Fixed{T,f}}, x::Integer) = Fixed{T,f}(convert(T,x)<<f,0) |
| 34 | +convert{T,f}(::Type{Fixed{T,f}}, x::AbstractFloat) = Fixed{T,f}(trunc(T,x)<<f + round(T, rem(x,1)*(1<<f)),0) |
| 35 | +convert{T,f}(::Type{Fixed{T,f}}, x::Rational) = Fixed{T,f}(x.num)/Fixed{T,f}(x.den) |
| 36 | + |
| 37 | +convert{T,f}(::Type{BigFloat}, x::Fixed{T,f}) = |
| 38 | + convert(BigFloat,x.i>>f) + convert(BigFloat,x.i&(1<<f - 1))/convert(BigFloat,1<<f) |
| 39 | +convert{TF<:AbstractFloat,T,f}(::Type{TF}, x::Fixed{T,f}) = |
| 40 | + convert(TF,x.i>>f) + convert(TF,x.i&(1<<f - 1))/convert(TF,1<<f) |
| 41 | + |
| 42 | +convert{T,f}(::Type{Bool}, x::Fixed{T,f}) = x.i!=0 |
| 43 | +function convert{TI<:Integer, T,f}(::Type{TI}, x::Fixed{T,f}) |
| 44 | + isinteger(x) || throw(InexactError()) |
| 45 | + convert(TI, x.i>>f) |
| 46 | +end |
| 47 | + |
| 48 | +convert{TR<:Rational,T,f}(::Type{TR}, x::Fixed{T,f}) = |
| 49 | + convert(TR, x.i>>f + (x.i&(1<<f-1))//(1<<f)) |
| 50 | + |
| 51 | +promote_rule{T,f,TI<:Integer}(ft::Type{Fixed{T,f}}, ::Type{TI}) = Fixed{T,f} |
| 52 | +promote_rule{T,f,TF<:AbstractFloat}(::Type{Fixed{T,f}}, ::Type{TF}) = TF |
| 53 | +promote_rule{T,f,TR}(::Type{Fixed{T,f}}, ::Type{Rational{TR}}) = Rational{TR} |
| 54 | + |
| 55 | +# TODO: Document and check that it still does the right thing. |
| 56 | +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))) |
0 commit comments