From 863693716c9dee7685b7cfe07a9437575bb149b8 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Thu, 15 Oct 2015 14:02:22 +0900 Subject: [PATCH 1/4] unify the concepts of Fixed and UFixed --- src/FixedPointNumbers.jl | 227 +++++++++++++++++++++++++++++++++++---- src/deprecations.jl | 1 - src/fixed.jl | 66 ------------ src/ufixed.jl | 176 ------------------------------ 4 files changed, 209 insertions(+), 261 deletions(-) delete mode 100644 src/fixed.jl delete mode 100644 src/ufixed.jl diff --git a/src/FixedPointNumbers.jl b/src/FixedPointNumbers.jl index 8c19a2e2..d166fe2c 100644 --- a/src/FixedPointNumbers.jl +++ b/src/FixedPointNumbers.jl @@ -13,9 +13,6 @@ import Base: ==, <, <=, -, +, *, /, ~, trunc, round, floor, ceil, bswap, div, fld, rem, mod, mod1, rem1, fld1, min, max, start, next, done, r_promote, reducedim_init -# T => BaseType -# f => Number of Bytes reserved for fractional part -abstract FixedPoint{T <: Integer, f} <: Real export FixedPoint, @@ -33,6 +30,7 @@ export ufixed12, ufixed14, ufixed16, + fixed16, # literal constructor constants uf8, uf10, @@ -42,25 +40,198 @@ export # Functions scaledual +# T => BaseType +# f => Number of Bytes reserved for fractional part +immutable FixedPoint{T <: Integer, f} <: Real + i::T + + # constructor for manipulating the representation; + # selected by passing an extra dummy argument + FixedPoint(i::T, _) = new(i) + FixedPoint(i::Integer,_) = new(i % T) + + FixedPoint(x) = convert(FixedPoint{T,f}, x) +end + +# basic typealiases for signed and unsigned +typealias Fixed{T <: Signed, f} FixedPoint{T, f} +typealias UFixed{T <: Unsigned, f} FixedPoint{T, f} + +# default provided typealiases +typealias Fixed16 Fixed{Int32, 16} +typealias UFixed8 UFixed{UInt8,8} +typealias UFixed10 UFixed{UInt16,10} +typealias UFixed12 UFixed{UInt16,12} +typealias UFixed14 UFixed{UInt16,14} +typealias UFixed16 UFixed{UInt16,16} + reinterpret(x::FixedPoint) = x.i +reinterpret{T,f}(::Type{T}, x::FixedPoint{T,f}) = x.i +reinterpret{T <: Integer,f}(::Type{FixedPoint{T,f}}, x::T) = FixedPoint{T,f}(x, 0) + +rawtype{T,f}(::Type{FixedPoint{T,f}}) = T +nbitsfrac{T,f}(::Type{FixedPoint{T,f}}) = f +rawone(v) = reinterpret(one(v)) -# comparison -=={T <: FixedPoint}(x::T, y::T) = x.i == y.i - <{T <: FixedPoint}(x::T, y::T) = x.i < y.i -<={T <: FixedPoint}(x::T, y::T) = x.i <= y.i +# comparisons +=={T <: FixedPoint}(x::T, y::T) = reinterpret(x) == reinterpret(y) + <{T <: FixedPoint}(x::T, y::T) = reinterpret(x) < reinterpret(y) +<={T <: FixedPoint}(x::T, y::T) = reinterpret(x) <= reinterpret(y) # predicates isinteger{T,f}(x::FixedPoint{T,f}) = (x.i&(1<> nbitsfrac(T),0) +# with rounding up: +function *{T<:FixedPoint}(x::T, y::T) + f = nbitsfrac(T) + i = Base.widemul(reinterpret(x),reinterpret(y)) + T((i + convert(widen(rawtype(T)), 1) << (f-1) )>>f,0) +end + +function /{T<:FixedPoint}(x::T, y::T) + f = nbitsfrac(T) + T(div(convert(widen(rawtype(T)), x.i) << f, y.i), 0) +end + +# Conversions to FixedPoint +convert{T,f}(::Type{FixedPoint{T,f}}, x::Integer) = + FixedPoint{T,f}(convert(T,x)<>f) + convert(BigFloat,x.i&(1<>f) + convert(TF,x.i&(1<>f) +end +# convert{T<:Integer}(::Type{T}, x::UFixed) = convert(T, x*(1/one(T))) + +convert{TR<:Rational,T,f}(::Type{TR}, x::FixedPoint{T,f}) = + convert(TR, x.i>>f + (x.i&(1< eps(T) ? Float64 : Float32 +# @eval begin +# promote_rule(::Type{$T}, ::Type{$Ti}) = $Tp +# end +# end +# end + +# Math functions +trunc{T<:FixedPoint}(x::T) = T(div(reinterpret(x), rawone(T))*rawone(T),0) +floor{T<:FixedPoint}(x::T) = trunc(x) + +trunc{T<:Integer}(::Type{T}, x::FixedPoint) = convert(T, div(reinterpret(x), rawone(x))) +round{T<:Integer}(::Type{T}, x::FixedPoint) = round(T, reinterpret(x)/rawone(x)) +floor{T<:Integer}(::Type{T}, x::FixedPoint) = trunc(T, x) + ceil{T<:Integer}(::Type{T}, x::FixedPoint) = ceil(T, reinterpret(x)/rawone(x)) +trunc(x::FixedPoint) = trunc(Int, x) # Already defined? +round(x::FixedPoint) = round(Int, x) +floor(x::FixedPoint) = floor(Int, x) # Already defined? + ceil(x::FixedPoint) = ceil(Int, x) + +# for T in UF +# f = nbitsfrac(T) +# R = rawtype(T) +# roundmask = convert(R, 1<<(f-1)) +# k = 8*sizeof(R)-f +# ceilmask = (typemax(R)<>k +# @eval begin +# round(x::$T) = (y = trunc(x); return convert(rawtype($T), reinterpret(x)-reinterpret(y))&$roundmask>0 ? $T(y+one($T)) : y) +# ceil(x::$T) = (y = trunc(x); return convert(rawtype($T), reinterpret(x)-reinterpret(y))&$ceilmask >0 ? $T(y+one($T)) : y) +# end +# end + +for f in (:div, :fld, :rem, :mod, :mod1, :rem1, :fld1, :min, :max) + @eval begin + $f{T<:FixedPoint}(x::T, y::T) = T($f(reinterpret(x),reinterpret(y)),0) + end +end +function minmax{T<:UFixed}(x::T, y::T) + a, b = minmax(reinterpret(x), reinterpret(y)) + T(a,0), T(b,0) +end + +# Special function +decompose{T,f}(x::FixedPoint{T,f}) = reinterpret(x), -f, 1 +# function decompose(x::UFixed) +# g = gcd(reinterpret(x), rawone(x)) +# div(reinterpret(x),g), 0, div(rawone(x),g) +# end + +bswap{T <: Union{UInt8, Int8}, f}(x::FixedPoint{T,f}) = x +bswap{T <: FixedPoint}(x::T) = T(bswap(reinterpret(x)),0) # Promotions for reductions const Treduce = Float64 @@ -75,14 +246,6 @@ reducedim_init{T<:FixedPoint}(f::IdFun, op::MulFun, A::AbstractArray{T}, region) = reducedim_initarray(A, region, one(Treduce)) -# TODO: rewrite this by @generated -for T in tuple(Fixed16, UF...) - R = rawtype(T) - @eval begin - reinterpret(::Type{$R}, x::$T) = x.i - end -end - # When multiplying by a float, reduce two multiplies to one. # Particularly useful for arrays. scaledual(Tdual::Type, x) = one(Tdual), x @@ -92,4 +255,32 @@ scaledual{Tdual<:Number}(b::Tdual, x) = b, x @compat scaledual{Tdual<:Number, T<:FixedPoint}(b::Tdual, x::Union{T,AbstractArray{T}}) = convert(Tdual, b/one(T)), reinterpret(rawtype(T), x) +# Show +function show(io::IO, x::FixedPoint) + print(io, typeof(x)) + print(io, "(") + showcompact(io, x) + print(io, ")") +end + +const _log2_10 = 3.321928094887362 +showcompact{T,f}(io::IO, x::FixedPoint{T,f}) = show(io, round(convert(Float64,x), ceil(Int,f/_log2_10))) + +# Iteration +# The main subtlety here is that iterating over 0x00uf8:0xffuf8 will wrap around +# unless we iterate using a wider type +start{T<:FixedPoint}(r::StepRange{T}) = convert(typeof(reinterpret(r.start)+reinterpret(r.step)), reinterpret(r.start)) +next{T<:FixedPoint}(r::StepRange{T}, i::Integer) = (T(i,0), i+reinterpret(r.step)) +done{T<:FixedPoint}(r::StepRange{T}, i::Integer) = isempty(r) || (i > reinterpret(r.stop)) + +immutable UFixedConstructor{T,f} end +*{T,f}(n::Integer, ::UFixedConstructor{T,f}) = UFixed{T,f}(n,0) +const uf8 = UFixedConstructor{UInt8,8}() +const uf10 = UFixedConstructor{UInt16,10}() +const uf12 = UFixedConstructor{UInt16,12}() +const uf14 = UFixedConstructor{UInt16,14}() +const uf16 = UFixedConstructor{UInt16,16}() + +include("deprecations.jl") + end # module diff --git a/src/deprecations.jl b/src/deprecations.jl index 3b348871..bcbedb4e 100644 --- a/src/deprecations.jl +++ b/src/deprecations.jl @@ -10,4 +10,3 @@ import Base.@deprecate_binding @deprecate_binding Ufixed16 UFixed16 @deprecate_binding Fixed32 Fixed16 -@deprecate Fixed(x::Real) convert(Fixed{Int32, 16}, x) diff --git a/src/fixed.jl b/src/fixed.jl deleted file mode 100644 index f76970c8..00000000 --- a/src/fixed.jl +++ /dev/null @@ -1,66 +0,0 @@ -# 32-bit fixed point; parameter `f` is the number of fraction bits -immutable Fixed{T <: Signed,f} <: FixedPoint{T, f} - i::T - - # constructor for manipulating the representation; - # selected by passing an extra dummy argument - Fixed(i::Integer,_) = new(i % T) - - Fixed(x) = convert(Fixed{T,f}, x) -end - -typealias Fixed16 Fixed{Int32, 16} - - rawtype{T,f}(::Type{Fixed{T,f}}) = T -nbitsfrac{T,f}(::Type{Fixed{T,f}}) = f - -# basic operators --{T,f}(x::Fixed{T,f}) = Fixed{T,f}(-x.i,0) -abs{T,f}(x::Fixed{T,f}) = Fixed{T,f}(abs(x.i),0) - -+{T,f}(x::Fixed{T,f}, y::Fixed{T,f}) = Fixed{T,f}(x.i+y.i,0) --{T,f}(x::Fixed{T,f}, y::Fixed{T,f}) = Fixed{T,f}(x.i-y.i,0) - -# with truncation: -#*{f}(x::Fixed32{f}, y::Fixed32{f}) = Fixed32{f}(Base.widemul(x.i,y.i)>>f,0) -# with rounding up: -*{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) - -/{T,f}(x::Fixed{T,f}, y::Fixed{T,f}) = Fixed{T,f}(div(convert(widen(T), x.i) << f, y.i), 0) - - -# # conversions and promotions -convert{T,f}(::Type{Fixed{T,f}}, x::Integer) = Fixed{T,f}(convert(T,x)<>f) + convert(BigFloat,x.i&(1<>f) + convert(TF,x.i&(1<>f) -end - -convert{TR<:Rational,T,f}(::Type{TR}, x::Fixed{T,f}) = - convert(TR, x.i>>f + (x.i&(1<>f,0) -/{T,f}(x::UFixed{T,f}, y::UFixed{T,f}) = UFixed{T,f}(div(convert(widen(T), x.i)<>k - @eval begin - round(x::$T) = (y = trunc(x); return convert(rawtype($T), reinterpret(x)-reinterpret(y))&$roundmask>0 ? $T(y+one($T)) : y) - ceil(x::$T) = (y = trunc(x); return convert(rawtype($T), reinterpret(x)-reinterpret(y))&$ceilmask >0 ? $T(y+one($T)) : y) - end -end - -trunc{T<:Integer}(::Type{T}, x::UFixed) = convert(T, div(reinterpret(x), rawone(x))) -round{T<:Integer}(::Type{T}, x::UFixed) = round(T, reinterpret(x)/rawone(x)) -floor{T<:Integer}(::Type{T}, x::UFixed) = trunc(T, x) - ceil{T<:Integer}(::Type{T}, x::UFixed) = ceil(T, reinterpret(x)/rawone(x)) -trunc(x::UFixed) = trunc(Int, x) -round(x::UFixed) = round(Int, x) -floor(x::UFixed) = floor(Int, x) - ceil(x::UFixed) = ceil(Int, x) - -isfinite(x::UFixed) = true -isnan(x::UFixed) = false -isinf(x::UFixed) = false - -bswap{f}(x::UFixed{UInt8,f}) = x -bswap(x::UFixed) = typeof(x)(bswap(reinterpret(x)),0) - -for f in (:div, :fld, :rem, :mod, :mod1, :rem1, :fld1, :min, :max) - @eval begin - $f{T<:UFixed}(x::T, y::T) = T($f(reinterpret(x),reinterpret(y)),0) - end -end -function minmax{T<:UFixed}(x::T, y::T) - a, b = minmax(reinterpret(x), reinterpret(y)) - T(a,0), T(b,0) -end - -# Iteration -# The main subtlety here is that iterating over 0x00uf8:0xffuf8 will wrap around -# unless we iterate using a wider type -if VERSION < v"0.3-" - start{T<:UFixed}(r::Range{T}) = convert(typeof(reinterpret(r.start)+reinterpret(r.step)), reinterpret(r.start)) - next{T<:UFixed}(r::Range{T}, i::Integer) = (T(i,0), i+reinterpret(r.step)) - done{T<:UFixed}(r::Range{T}, i::Integer) = isempty(r) || (i > r.len) -else - start{T<:UFixed}(r::StepRange{T}) = convert(typeof(reinterpret(r.start)+reinterpret(r.step)), reinterpret(r.start)) - next{T<:UFixed}(r::StepRange{T}, i::Integer) = (T(i,0), i+reinterpret(r.step)) - done{T<:UFixed}(r::StepRange{T}, i::Integer) = isempty(r) || (i > reinterpret(r.stop)) -end - -function decompose(x::UFixed) - g = gcd(reinterpret(x), rawone(x)) - div(reinterpret(x),g), 0, div(rawone(x),g) -end - -# Promotions -for T in UF - @eval begin - promote_rule(::Type{$T}, ::Type{Float32}) = Float32 - promote_rule(::Type{$T}, ::Type{Float64}) = Float64 - promote_rule{TR<:Rational}(::Type{$T}, ::Type{TR}) = TR - end - for Ti in (Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64) - Tp = eps(convert(Float32, typemax(Ti))) > eps(T) ? Float64 : Float32 - @eval begin - promote_rule(::Type{$T}, ::Type{$Ti}) = $Tp - end - end -end - -# Show -function show{T,f}(io::IO, x::UFixed{T,f}) - print(io, "UFixed", f) - print(io, "(") - showcompact(io, x) - print(io, ")") -end -showcompact{T,f}(io::IO, x::UFixed{T,f}) = show(io, round(convert(Float64,x), ceil(Int,f/_log2_10))) From 80f986f114d80574e3a58efe282d06b992d6c27a Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 19 Oct 2015 23:07:56 +0900 Subject: [PATCH 2/4] special case some methods for Unsigned --- src/FixedPointNumbers.jl | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/FixedPointNumbers.jl b/src/FixedPointNumbers.jl index d166fe2c..123ec8ba 100644 --- a/src/FixedPointNumbers.jl +++ b/src/FixedPointNumbers.jl @@ -1,4 +1,4 @@ -VERSION >= v"0.4.0-dev+6521" && __precompile__() +# ERSION >= v"0.4.0-dev+6521" && __precompile__() module FixedPointNumbers @@ -94,10 +94,13 @@ eps{T<:FixedPoint}(::T) = eps(T) sizeof{T<:FixedPoint}(::Type{T}) = sizeof(rawtype(T)) zero{T <: FixedPoint}(::Type{T}) = T(zero(rawtype(T)),0) - one{T <: FixedPoint}(::Type{T}) = T(2^nbitsfrac(T)-1,0) -zero(x::FixedPoint) = zero(typeof(x)) - one(x::FixedPoint) = one(typeof(x)) - +function one{T,f}(::Type{FixedPoint{T, f}}) + if T <: Unsigned || sizeof(T) * 8 > f + return T(2^nbitsfrac(T)-1,0) + else + throw(DomainError()) + end +end # basic operators & arithmetics (-){T<:FixedPoint}(x::T) = T(-reinterpret(x), 0) @@ -131,13 +134,15 @@ convert{T,f}(::Type{Fixed{T,f}}, x::Rational) = FixedPoint{T,f}(x.num)/FixedPoint{T,f}(x.den) # Conversions from FixedPoint -convert{T,f}(::Type{BigFloat}, x::FixedPoint{T,f}) = +convert{T <: Signed,f}(::Type{BigFloat}, x::FixedPoint{T,f}) = convert(BigFloat,x.i>>f) + convert(BigFloat,x.i&(1<>f) + convert(TF,x.i&(1<>f) end -# convert{T<:Integer}(::Type{T}, x::UFixed) = convert(T, x*(1/one(T))) convert{TR<:Rational,T,f}(::Type{TR}, x::FixedPoint{T,f}) = convert(TR, x.i>>f + (x.i&(1< Date: Thu, 22 Oct 2015 14:50:22 +0900 Subject: [PATCH 3/4] rename reinterpret to getindex --- src/FixedPointNumbers.jl | 91 ++++++++++++++++++++-------------------- src/deprecations.jl | 2 + 2 files changed, 48 insertions(+), 45 deletions(-) diff --git a/src/FixedPointNumbers.jl b/src/FixedPointNumbers.jl index 123ec8ba..b9a88797 100644 --- a/src/FixedPointNumbers.jl +++ b/src/FixedPointNumbers.jl @@ -9,7 +9,7 @@ using Base: IdFun, AddFun, MulFun, reducedim_initarray import Base: ==, <, <=, -, +, *, /, ~, convert, promote_rule, show, showcompact, isinteger, abs, decompose, isnan, isinf, isfinite, - zero, one, typemin, typemax, realmin, realmax, eps, sizeof, reinterpret, + zero, one, typemin, typemax, realmin, realmax, eps, sizeof, reinterpret, getindex, trunc, round, floor, ceil, bswap, div, fld, rem, mod, mod1, rem1, fld1, min, max, start, next, done, r_promote, reducedim_init @@ -65,21 +65,21 @@ typealias UFixed12 UFixed{UInt16,12} typealias UFixed14 UFixed{UInt16,14} typealias UFixed16 UFixed{UInt16,16} -reinterpret(x::FixedPoint) = x.i -reinterpret{T,f}(::Type{T}, x::FixedPoint{T,f}) = x.i +getindex(x::FixedPoint) = x.i +reinterpret{T,f}(::Type{T}, x::FixedPoint{T,f}) = x[] reinterpret{T <: Integer,f}(::Type{FixedPoint{T,f}}, x::T) = FixedPoint{T,f}(x, 0) rawtype{T,f}(::Type{FixedPoint{T,f}}) = T nbitsfrac{T,f}(::Type{FixedPoint{T,f}}) = f -rawone(v) = reinterpret(one(v)) +rawone(v) = one(v)[] # comparisons -=={T <: FixedPoint}(x::T, y::T) = reinterpret(x) == reinterpret(y) - <{T <: FixedPoint}(x::T, y::T) = reinterpret(x) < reinterpret(y) -<={T <: FixedPoint}(x::T, y::T) = reinterpret(x) <= reinterpret(y) +=={T <: FixedPoint}(x::T, y::T) = x[] == y[] + <{T <: FixedPoint}(x::T, y::T) = x[] < y[] +<={T <: FixedPoint}(x::T, y::T) = x[] <= y[] # predicates -isinteger{T,f}(x::FixedPoint{T,f}) = (x.i&(1< f - return T(2^nbitsfrac(T)-1,0) +one{T <: Unsigned, f}(::Type{FixedPoint{T, f}}) = FixedPoint{T, f}(2^f-1,0) +function one{T <: Signed,f}(::Type{FixedPoint{T, f}}) + if sizeof(T) * 8 > f + return FixedPoint{T, f}(2^f-1,0) else throw(DomainError()) end end # basic operators & arithmetics -(-){T<:FixedPoint}(x::T) = T(-reinterpret(x), 0) -(~){T<:FixedPoint}(x::T) = T(~reinterpret(x), 0) -abs{T<:FixedPoint}(x::T) = T(abs(reinterpret(x)),0) +(-){T<:FixedPoint}(x::T) = T(-x[], 0) +(~){T<:FixedPoint}(x::T) = T(~x[], 0) +abs{T<:FixedPoint}(x::T) = T(abs(x[]),0) -+{T<:FixedPoint}(x::T, y::T) = T(reinterpret(x) + reinterpret(y),0) --{T<:FixedPoint}(x::T, y::T) = T(reinterpret(x) - reinterpret(y),0) ++{T<:FixedPoint}(x::T, y::T) = T(x[] + y[],0) +-{T<:FixedPoint}(x::T, y::T) = T(x[] - y[],0) # with truncation: # *{T<:FixedPoint}(x::T, y::T) = -# T(Base.widemul(reinterpret(x),reinterpret(y)) >> nbitsfrac(T),0) +# T(Base.widemul(x[],y[]) >> nbitsfrac(T),0) # with rounding up: function *{T<:FixedPoint}(x::T, y::T) f = nbitsfrac(T) - i = Base.widemul(reinterpret(x),reinterpret(y)) + i = Base.widemul(x[],y[]) T((i + convert(widen(rawtype(T)), 1) << (f-1) )>>f,0) end function /{T<:FixedPoint}(x::T, y::T) f = nbitsfrac(T) - T(div(convert(widen(rawtype(T)), x.i) << f, y.i), 0) + T(div(convert(widen(rawtype(T)), x[]) << f, y.i), 0) end # Conversions to FixedPoint @@ -135,31 +136,31 @@ convert{T,f}(::Type{Fixed{T,f}}, x::Rational) = # Conversions from FixedPoint convert{T <: Signed,f}(::Type{BigFloat}, x::FixedPoint{T,f}) = - convert(BigFloat,x.i>>f) + convert(BigFloat,x.i&(1<>f) + convert(BigFloat,x[]&(1<>f) + convert(TF,x.i&(1<>f) + convert(TF,x[]&(1<>f) + convert(TI, x[]>>f) end convert{TR<:Rational,T,f}(::Type{TR}, x::FixedPoint{T,f}) = - convert(TR, x.i>>f + (x.i&(1<>f + (x[]&(1<>k # @eval begin -# round(x::$T) = (y = trunc(x); return convert(rawtype($T), reinterpret(x)-reinterpret(y))&$roundmask>0 ? $T(y+one($T)) : y) -# ceil(x::$T) = (y = trunc(x); return convert(rawtype($T), reinterpret(x)-reinterpret(y))&$ceilmask >0 ? $T(y+one($T)) : y) +# round(x::$T) = (y = trunc(x); return convert(rawtype($T), x[]-y[])&$roundmask>0 ? $T(y+one($T)) : y) +# ceil(x::$T) = (y = trunc(x); return convert(rawtype($T), x[]-y[])&$ceilmask >0 ? $T(y+one($T)) : y) # end # end for f in (:div, :fld, :rem, :mod, :mod1, :rem1, :fld1, :min, :max) @eval begin - $f{T<:FixedPoint}(x::T, y::T) = T($f(reinterpret(x),reinterpret(y)),0) + $f{T<:FixedPoint}(x::T, y::T) = T($f(x[],y[]),0) end end function minmax{T<:UFixed}(x::T, y::T) - a, b = minmax(reinterpret(x), reinterpret(y)) + a, b = minmax(x[], y[]) T(a,0), T(b,0) end # Special function -decompose{T,f}(x::FixedPoint{T,f}) = reinterpret(x), -f, 1 +decompose{T,f}(x::FixedPoint{T,f}) = x[], -f, 1 # function decompose(x::UFixed) -# g = gcd(reinterpret(x), rawone(x)) -# div(reinterpret(x),g), 0, div(rawone(x),g) +# g = gcd(x[], rawone(x)) +# div(x[],g), 0, div(rawone(x),g) # end bswap{T <: Union{UInt8, Int8}, f}(x::FixedPoint{T,f}) = x -bswap{T <: FixedPoint}(x::T) = T(bswap(reinterpret(x)),0) +bswap{T <: FixedPoint}(x::T) = T(bswap(x[]),0) # Promotions for reductions const Treduce = Float64 @@ -273,9 +274,9 @@ showcompact{T,f}(io::IO, x::FixedPoint{T,f}) = show(io, round(convert(Float64,x) # Iteration # The main subtlety here is that iterating over 0x00uf8:0xffuf8 will wrap around # unless we iterate using a wider type -start{T<:FixedPoint}(r::StepRange{T}) = convert(typeof(reinterpret(r.start)+reinterpret(r.step)), reinterpret(r.start)) -next{T<:FixedPoint}(r::StepRange{T}, i::Integer) = (T(i,0), i+reinterpret(r.step)) -done{T<:FixedPoint}(r::StepRange{T}, i::Integer) = isempty(r) || (i > reinterpret(r.stop)) +start{T<:FixedPoint}(r::StepRange{T}) = convert(typeof(r.start[] + r.step[]), r.start[]) +next{T<:FixedPoint}(r::StepRange{T}, i::Integer) = (T(i,0), i+r.step[]) +done{T<:FixedPoint}(r::StepRange{T}, i::Integer) = isempty(r) || (i > r.stop[]) immutable UFixedConstructor{T,f} end *{T,f}(n::Integer, ::UFixedConstructor{T,f}) = UFixed{T,f}(n,0) diff --git a/src/deprecations.jl b/src/deprecations.jl index bcbedb4e..ab8c04c1 100644 --- a/src/deprecations.jl +++ b/src/deprecations.jl @@ -10,3 +10,5 @@ import Base.@deprecate_binding @deprecate_binding Ufixed16 UFixed16 @deprecate_binding Fixed32 Fixed16 + +@deprecate reinterpret(x::FixedPoint) getindex(x) From ee87107f7d5866a1d71150008e30151fd25667c4 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Thu, 22 Oct 2015 18:59:20 +0900 Subject: [PATCH 4/4] rounding fixes --- src/FixedPointNumbers.jl | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/FixedPointNumbers.jl b/src/FixedPointNumbers.jl index b9a88797..f75c82ac 100644 --- a/src/FixedPointNumbers.jl +++ b/src/FixedPointNumbers.jl @@ -152,10 +152,10 @@ function convert{TI<:Integer, T,f}(::Type{TI}, x::FixedPoint{T,f}) convert(TI, x[]>>f) end -convert{TR<:Rational,T,f}(::Type{TR}, x::FixedPoint{T,f}) = - convert(TR, x[]>>f + (x[]&(1<> f + (x[] & (1 << f - 1)) // (1 << f)) +convert{Ti<:Integer}(::Type{Rational{Ti}}, x::UFixed) = convert(Ti, x[])//convert(Ti, rawone(x)) +convert(::Type{Rational}, x::UFixed) = x[]//rawone(x) # Special conversions for constructors convert{T<:FixedPoint}(::Type{T}, x::T) = x @@ -193,17 +193,27 @@ promote_rule{T <: FixedPoint,TR <: Rational}(::Type{T}, ::Type{TR}) = TR # end # Math functions -trunc{T<:FixedPoint}(x::T) = T(div(x[], rawone(T))*rawone(T),0) +# Round towards negative infinity +trunc{T<:FixedPoint}(x::T) = T(x[] & ~(1 << nbitsfrac(T) - 1), 0) +# Round towards negative infinity floor{T<:FixedPoint}(x::T) = trunc(x) +# Round towards positive infinity +ceil{T<:FixedPoint}(x::T) = trunc(T(x[] + 1 << (nbitsfrac(T)-1), 0)) +# Round towards even +function round{T<:FixedPoint}(x::T) + even = x[] & (1 << nbitsfrac(T)) == 0 + if even + return floor(x) + else + return ceil(x) + end +end -trunc{T<:Integer}(::Type{T}, x::FixedPoint) = convert(T, div(x[], rawone(x))) -round{T<:Integer}(::Type{T}, x::FixedPoint) = round(T, x[]/rawone(x)) +trunc{TI<:Integer, T <: FixedPoint}(::Type{TI}, x::T) = + convert(TI, x[] >> nbitsfrac(T)) floor{T<:Integer}(::Type{T}, x::FixedPoint) = trunc(T, x) - ceil{T<:Integer}(::Type{T}, x::FixedPoint) = ceil(T, x[]/rawone(x)) -trunc(x::FixedPoint) = trunc(Int, x) # Already defined? -round(x::FixedPoint) = round(Int, x) -floor(x::FixedPoint) = floor(Int, x) # Already defined? - ceil(x::FixedPoint) = ceil(Int, x) +ceil{T<:Integer}(::Type{T}, x::FixedPoint) = trunc(T, ceil(x)) +round{T<:Integer}(::Type{T}, x::FixedPoint) = trunc(T, round(x)) # for T in UF # f = nbitsfrac(T)