Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ notifications:
script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
- julia -e 'Pkg.clone(pwd()); Pkg.build("FixedPointNumbers")'
- julia -e 'if VERSION >= v"0.6.0-dev.565" Pkg.test("FixedPointNumbers"; coverage=true); else cd(Pkg.dir("FixedPointNumbers", "test")); include("runtests.jl"); end '
- julia -e 'Pkg.test("FixedPointNumbers"; coverage=true)'
after_success:
# push coverage results to Codecov
- julia -e 'if VERSION >= v"0.6.0-dev.565" cd(Pkg.dir("FixedPointNumbers")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder()); end'
- julia -e 'cd(Pkg.dir("FixedPointNumbers")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())'
3 changes: 1 addition & 2 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
julia 0.5
Compat 0.17.0
julia 0.6
80 changes: 39 additions & 41 deletions src/FixedPointNumbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ if isdefined(Base, :rem1)
end
using Base: @pure

using Compat

# T => BaseType
# f => Number of Bytes reserved for fractional part
@compat abstract type FixedPoint{T <: Integer, f} <: Real end
abstract type FixedPoint{T <: Integer, f} <: Real end


export
Expand All @@ -39,21 +37,21 @@ export
scaledual

reinterpret(x::FixedPoint) = x.i
reinterpret{T,f}(::Type{T}, x::FixedPoint{T,f}) = x.i
reinterpret(::Type{T}, x::FixedPoint{T,f}) where {T,f} = x.i

# construction using the (approximate) intended value, i.e., N0f8
*{X<:FixedPoint}(x::Real, ::Type{X}) = X(x)
*(x::Real, ::Type{X}) where {X<:FixedPoint} = X(x)

# 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
==(x::T, y::T) where {T <: FixedPoint} = x.i == y.i
<(x::T, y::T) where {T <: FixedPoint} = x.i < y.i
<=(x::T, y::T) where {T <: FixedPoint} = x.i <= y.i
"""
isapprox(x::FixedPoint, y::FixedPoint; rtol=0, atol=max(eps(x), eps(y)))

For FixedPoint numbers, the default criterion is that `x` and `y` differ by no more than `eps`, the separation between adjacent fixed-point numbers.
"""
function isapprox{T<:FixedPoint}(x::T, y::T; rtol=0, atol=max(eps(x), eps(y)))
function isapprox(x::T, y::T; rtol=0, atol=max(eps(x), eps(y))) where {T <: FixedPoint}
maxdiff = T(atol+rtol*max(abs(x), abs(y)))
rx, ry, rd = reinterpret(x), reinterpret(y), reinterpret(maxdiff)
abs(signed(widen1(rx))-signed(widen1(ry))) <= rd
Expand All @@ -63,13 +61,13 @@ function isapprox(x::FixedPoint, y::FixedPoint; rtol=0, atol=max(eps(x), eps(y))
end

# predicates
isinteger{T,f}(x::FixedPoint{T,f}) = (x.i&(1<<f-1)) == 0
isinteger(x::FixedPoint{T,f}) where {T,f} = (x.i&(1<<f-1)) == 0

# traits
typemax{T<: FixedPoint}(::Type{T}) = T(typemax(rawtype(T)), 0)
typemin{T<: FixedPoint}(::Type{T}) = T(typemin(rawtype(T)), 0)
realmin{T<: FixedPoint}(::Type{T}) = eps(T)
realmax{T<: FixedPoint}(::Type{T}) = typemax(T)
typemax(::Type{T}) where {T <: FixedPoint} = T(typemax(rawtype(T)), 0)
typemin(::Type{T}) where {T <: FixedPoint} = T(typemin(rawtype(T)), 0)
realmin(::Type{T}) where {T <: FixedPoint} = eps(T)
realmax(::Type{T}) where {T <: FixedPoint} = typemax(T)

widen1(::Type{Int8}) = Int16
widen1(::Type{UInt8}) = UInt16
Expand All @@ -84,84 +82,84 @@ widen1(x::Integer) = x % widen1(typeof(x))

const ShortInts = Union{Int8,UInt8,Int16,UInt16}

floattype{T<:ShortInts,f}(::Type{FixedPoint{T,f}}) = Float32
floattype{T<:Integer,f}(::Type{FixedPoint{T,f}}) = Float64
floattype{F<:FixedPoint}(::Type{F}) = floattype(supertype(F))
floattype(::Type{FixedPoint{T,f}}) where {T <: ShortInts,f} = Float32
floattype(::Type{FixedPoint{T,f}}) where {T <: Integer,f} = Float64
floattype(::Type{F}) where {F <: FixedPoint} = floattype(supertype(F))
floattype(x::FixedPoint) = floattype(typeof(x))

nbitsfrac{T<:Integer,f}(::Type{FixedPoint{T,f}}) = f
nbitsfrac{F<:FixedPoint}(::Type{F}) = nbitsfrac(supertype(F))
nbitsfrac(::Type{FixedPoint{T,f}}) where {T <: Integer,f} = f
nbitsfrac(::Type{F}) where {F <: FixedPoint} = nbitsfrac(supertype(F))

rawtype{T<:Integer,f}(::Type{FixedPoint{T,f}}) = T
rawtype{F<:FixedPoint}(::Type{F}) = rawtype(supertype(F))
rawtype(::Type{FixedPoint{T,f}}) where {T <: Integer,f} = T
rawtype(::Type{F}) where {F <: FixedPoint} = rawtype(supertype(F))
rawtype(x::FixedPoint) = rawtype(typeof(x))

# This IOBuffer is used during module definition to generate typealias names
_iotypealias = IOBuffer()

# Printing. These are used to generate type-symbols, so we need them
# before we include any files.
function showtype{X<:FixedPoint}(io::IO, ::Type{X})
function showtype(io::IO, ::Type{X}) where {X <: FixedPoint}
print(io, typechar(X))
f = nbitsfrac(X)
m = sizeof(X)*8-f-signbits(X)
print(io, m, 'f', f)
io
end
function show{T,f}(io::IO, x::FixedPoint{T,f})
function show(io::IO, x::FixedPoint{T,f}) where {T,f}
showcompact(io, x)
showtype(io, typeof(x))
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)))
showcompact(io::IO, x::FixedPoint{T,f}) where {T,f} = show(io, round(convert(Float64,x), ceil(Int,f/_log2_10)))


include("fixed.jl")
include("normed.jl")
include("deprecations.jl")

eps{T<:FixedPoint}(::Type{T}) = T(one(rawtype(T)),0)
eps{T<:FixedPoint}(::T) = eps(T)
sizeof{T<:FixedPoint}(::Type{T}) = sizeof(rawtype(T))
eps(::Type{T}) where {T <: FixedPoint} = T(one(rawtype(T)),0)
eps(::T) where {T <: FixedPoint} = eps(T)
sizeof(::Type{T}) where {T <: FixedPoint} = sizeof(rawtype(T))

# Promotions for reductions
const Treduce = Float64
r_promote{T}(::typeof(+), x::FixedPoint{T}) = Treduce(x)
r_promote{T}(::typeof(*), x::FixedPoint{T}) = Treduce(x)
r_promote(::typeof(+), x::FixedPoint{T}) where {T} = Treduce(x)
r_promote(::typeof(*), x::FixedPoint{T}) where {T} = Treduce(x)

reducedim_init{T<:FixedPoint}(f::typeof(identity),
reducedim_init(f::typeof(identity),
op::typeof(+),
A::AbstractArray{T}, region) =
A::AbstractArray{T}, region) where {T <: FixedPoint} =
reducedim_initarray(A, region, zero(Treduce))
reducedim_init{T<:FixedPoint}(f::typeof(identity),
reducedim_init(f::typeof(identity),
op::typeof(*),
A::AbstractArray{T}, region) =
A::AbstractArray{T}, region) where {T <: FixedPoint} =
reducedim_initarray(A, region, one(Treduce))

for f in (:div, :fld, :fld1)
@eval begin
$f{T<:FixedPoint}(x::T, y::T) = $f(reinterpret(x),reinterpret(y))
$f(x::T, y::T) where {T <: FixedPoint} = $f(reinterpret(x),reinterpret(y))
end
end
for f in (:rem, :mod, :mod1, :rem1, :min, :max)
if f === :rem1 && !isdefined(Base, :rem1)
continue
end
@eval begin
$f{T<:FixedPoint}(x::T, y::T) = T($f(reinterpret(x),reinterpret(y)),0)
$f(x::T, y::T) where {T <: FixedPoint} = T($f(reinterpret(x),reinterpret(y)),0)
end
end

# When multiplying by a float, reduce two multiplies to one.
# Particularly useful for arrays.
scaledual(Tdual::Type, x) = one(Tdual), x
scaledual{Tdual<:Number}(b::Tdual, x) = b, x
scaledual{T<:FixedPoint}(Tdual::Type, x::Union{T,AbstractArray{T}}) =
scaledual(b::Tdual, x) where {Tdual <: Number} = b, x
scaledual(Tdual::Type, x::Union{T,AbstractArray{T}}) where {T <: FixedPoint} =
convert(Tdual, 1/one(T)), reinterpret(rawtype(T), x)
scaledual{Tdual<:Number, T<:FixedPoint}(b::Tdual, x::Union{T,AbstractArray{T}}) =
scaledual(b::Tdual, x::Union{T,AbstractArray{T}}) where {Tdual <: Number,T <: FixedPoint} =
convert(Tdual, b/one(T)), reinterpret(rawtype(T), x)

@noinline function throw_converterror{T<:FixedPoint}(::Type{T}, x)
@noinline function throw_converterror(::Type{T}, x) where {T <: FixedPoint}
n = 2^(8*sizeof(T))
bitstring = sizeof(T) == 1 ? "an 8-bit" : "a $(8*sizeof(T))-bit"
io = IOBuffer()
Expand All @@ -170,7 +168,7 @@ scaledual{Tdual<:Number, T<:FixedPoint}(b::Tdual, x::Union{T,AbstractArray{T}})
throw(ArgumentError("$T is $bitstring type representing $n values from $Tmin to $Tmax; cannot represent $x"))
end

rand{T<:FixedPoint}(::Type{T}) = reinterpret(T, rand(rawtype(T)))
rand{T<:FixedPoint}(::Type{T}, sz::Dims) = reinterpret(T, rand(rawtype(T), sz))
rand(::Type{T}) where {T <: FixedPoint} = reinterpret(T, rand(rawtype(T)))
rand(::Type{T}, sz::Dims) where {T <: FixedPoint} = reinterpret(T, rand(rawtype(T), sz))

end # module
8 changes: 1 addition & 7 deletions src/deprecations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,10 @@ const UF = (N0f8, N6f10, N4f12, N2f14, N0f16)
@deprecate ufixed14(x) N2f14(x)
@deprecate ufixed16(x) N0f16(x)

Compat.@dep_vectorize_1arg Real ufixed8
Compat.@dep_vectorize_1arg Real ufixed10
Compat.@dep_vectorize_1arg Real ufixed12
Compat.@dep_vectorize_1arg Real ufixed14
Compat.@dep_vectorize_1arg Real ufixed16

## The next lines mimic the floating-point literal syntax "3.2f0"
# construction using a UInt, i.e., 0xccuf8
struct NormedConstructor{T,f} end
function *{T,f}(n::Integer, ::NormedConstructor{T,f})
function *(n::Integer, ::NormedConstructor{T,f}) where {T,f}
i = 8*sizeof(T)-f
io = IOBuffer()
show(io, n)
Expand Down
52 changes: 26 additions & 26 deletions src/fixed.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ struct Fixed{T <: Signed,f} <: FixedPoint{T, f}

# constructor for manipulating the representation;
# selected by passing an extra dummy argument
(::Type{Fixed{T, f}}){T, f}(i::Integer, _) = new{T, f}(i % T)
(::Type{Fixed{T, f}}){T, f}(x) = convert(Fixed{T,f}, x)
(::Type{Fixed{T, f}})(i::Integer, _) where {T,f} = new{T, f}(i % T)
(::Type{Fixed{T, f}})(x) where {T,f} = convert(Fixed{T,f}, x)
end

reinterpret{T<:Signed, f}(::Type{Fixed{T,f}}, x::T) = Fixed{T,f}(x, 0)
reinterpret(::Type{Fixed{T,f}}, x::T) where {T <: Signed,f} = Fixed{T,f}(x, 0)

typechar{X<:Fixed}(::Type{X}) = 'Q'
signbits{X<:Fixed}(::Type{X}) = 1
typechar(::Type{X}) where {X <: Fixed} = 'Q'
signbits(::Type{X}) where {X <: Fixed} = 1

for T in (Int8, Int16, Int32, Int64)
for f in 0:sizeof(T)*8-1
Expand All @@ -24,52 +24,52 @@ for T in (Int8, Int16, Int32, Int64)
end

# 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)
-(x::Fixed{T,f}) where {T,f} = Fixed{T,f}(-x.i,0)
abs(x::Fixed{T,f}) where {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)
+(x::Fixed{T,f}, y::Fixed{T,f}) where {T,f} = Fixed{T,f}(x.i+y.i,0)
-(x::Fixed{T,f}, y::Fixed{T,f}) where {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)
*(x::Fixed{T,f}, y::Fixed{T,f}) where {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)
/(x::Fixed{T,f}, y::Fixed{T,f}) where {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}(round(T, convert(widen1(T),x)<<f),0)
convert{T,f}(::Type{Fixed{T,f}}, x::AbstractFloat) = Fixed{T,f}(round(T, trunc(widen1(T),x)<<f + rem(x,1)*(1<<f)),0)
convert{T,f}(::Type{Fixed{T,f}}, x::Rational) = Fixed{T,f}(x.num)/Fixed{T,f}(x.den)
convert(::Type{Fixed{T,f}}, x::Integer) where {T,f} = Fixed{T,f}(round(T, convert(widen1(T),x)<<f),0)
convert(::Type{Fixed{T,f}}, x::AbstractFloat) where {T,f} = Fixed{T,f}(round(T, trunc(widen1(T),x)<<f + rem(x,1)*(1<<f)),0)
convert(::Type{Fixed{T,f}}, x::Rational) where {T,f} = Fixed{T,f}(x.num)/Fixed{T,f}(x.den)

rem{T,f}(x::Integer, ::Type{Fixed{T,f}}) = Fixed{T,f}(rem(x,T)<<f,0)
rem{T,f}(x::Real, ::Type{Fixed{T,f}}) = Fixed{T,f}(rem(Integer(trunc(x)),T)<<f + rem(Integer(round(rem(x,1)*(1<<f))),T),0)
rem(x::Integer, ::Type{Fixed{T,f}}) where {T,f} = Fixed{T,f}(rem(x,T)<<f,0)
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)*(1<<f))),T),0)

# convert{T,f}(::Type{AbstractFloat}, x::Fixed{T,f}) = convert(floattype(x), x)
float(x::Fixed) = convert(floattype(x), x)

convert{T,f}(::Type{BigFloat}, x::Fixed{T,f}) =
convert(::Type{BigFloat}, x::Fixed{T,f}) where {T,f} =
convert(BigFloat,x.i>>f) + convert(BigFloat,x.i&(1<<f - 1))/convert(BigFloat,1<<f)
convert{TF<:AbstractFloat,T,f}(::Type{TF}, x::Fixed{T,f}) =
convert(::Type{TF}, x::Fixed{T,f}) where {TF <: AbstractFloat,T,f} =
convert(TF,x.i>>f) + convert(TF,x.i&(1<<f - 1))/convert(TF,1<<f)

convert{T,f}(::Type{Bool}, x::Fixed{T,f}) = x.i!=0
function convert{T,f}(::Type{Integer}, x::Fixed{T,f})
convert(::Type{Bool}, x::Fixed{T,f}) where {T,f} = x.i!=0
function convert(::Type{Integer}, x::Fixed{T,f}) where {T,f}
isinteger(x) || throw(InexactError())
convert(Integer, x.i>>f)
end
function convert{TI<:Integer, T,f}(::Type{TI}, x::Fixed{T,f})
function convert(::Type{TI}, x::Fixed{T,f}) where {TI <: Integer,T,f}
isinteger(x) || throw(InexactError())
convert(TI, x.i>>f)
end

convert{TR<:Rational,T,f}(::Type{TR}, x::Fixed{T,f}) =
convert(::Type{TR}, x::Fixed{T,f}) where {TR <: Rational,T,f} =
convert(TR, x.i>>f + (x.i&(1<<f-1))//(1<<f))

promote_rule{T,f,TI<:Integer}(ft::Type{Fixed{T,f}}, ::Type{TI}) = Fixed{T,f}
promote_rule{T,f,TF<:AbstractFloat}(::Type{Fixed{T,f}}, ::Type{TF}) = TF
promote_rule{T,f,TR}(::Type{Fixed{T,f}}, ::Type{Rational{TR}}) = Rational{TR}
promote_rule(ft::Type{Fixed{T,f}}, ::Type{TI}) where {T,f,TI <: Integer} = Fixed{T,f}
promote_rule(::Type{Fixed{T,f}}, ::Type{TF}) where {T,f,TF <: AbstractFloat} = TF
promote_rule(::Type{Fixed{T,f}}, ::Type{Rational{TR}}) where {T,f,TR} = Rational{TR}

# TODO: Document and check that it still does the right thing.
decompose{T,f}(x::Fixed{T,f}) = x.i, -f, 1
decompose(x::Fixed{T,f}) where {T,f} = x.i, -f, 1
Loading