Skip to content

[RFC/WIP] Homogenise design #27

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 5, 2015
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
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ os:
- linux
- osx
julia:
- 0.3
- 0.4
- nightly
notifications:
email: false
script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
- julia -e 'Pkg.clone(pwd()); Pkg.build("FixedPointNumbers")'
- julia -e 'cd(Pkg.dir("FixedPointNumbers", "test")); include("runtests.jl")'
23 changes: 9 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,23 @@ This library exports two categories of fixed-point types. Fixed-point types are
used like any other number: they can be added, multiplied, raised to a power,
etc. In many cases these operations result in conversion to floating-point types.

## Fixed32 (signed fixed-point numbers)
# Type hierarchy
This library defines an abstract type `FixedPoint{T <: Integer, f}` as a subtype of `Real`. The parameter `T` is the underlying representation and `f` is the number of fraction bits.

For signed integers, there is a 32-bit fixed-point type `Fixed32{f}`.
The parameter `f` is the number of fraction bits. There is also an abstract subtype of
`Real` called `Fixed`.
For signed integers, there is a fixed-point type `Fixed{T, f}` and for unsigned integers, there is the `UFixed{T, f}` type.

To use it, convert numbers to a `Fixed32` type, or call `Fixed32(x)`, which will default
to constructing a `Fixed32{16}`.

## Ufixed (unsigned fixed-point numbers)

For unsigned integers, there is a family of subtypes of the abstract `Ufixed` type.
These types, built with `f` fraction bits, map the closed interval [0.0,1.0]
to the span of numbers with `f` bits.
For example, the `Ufixed8` type is represented internally by a `Uint8`, and makes
For example, the `UFixed8` type is represented internally by a `UInt8`, and makes
`0x00` equivalent to `0.0` and `0xff` to `1.0`.
The types `Ufixed10`, `Ufixed12`, `Ufixed14`, and `Ufixed16` are all based on `Uint16`
The types `UFixed10`, `UFixed12`, `UFixed14`, and `UFixed16` are all based on `UInt16`
and reach the value `1.0` at 10, 12, 14, and 16 bits, respectively (`0x03ff`, `0x0fff`,
`0x3fff`, and `0xffff`).

To construct such a number, use `convert(Ufixed12, 1.3)`, `ufixed12(1.3)`, or the literal syntax `0x14ccuf12`.
The latter syntax means to construct a `Ufixed12` (it ends in `uf12`) from the `Uint16` value
To construct such a number, use `convert(UFixed12, 1.3)`, `ufixed12(1.3)`, or the literal syntax `0x14ccuf12`.
The latter syntax means to construct a `UFixed12` (it ends in `uf12`) from the `UInt16` value
`0x14cc`.

There currently is no literal syntax for signed `Fixed` numbers.

[wikipedia]: http://en.wikipedia.org/wiki/Fixed-point_arithmetic
2 changes: 1 addition & 1 deletion REQUIRE
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
julia 0.3
julia 0.4-
Compat 0.2.2
41 changes: 28 additions & 13 deletions src/FixedPointNumbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,20 @@ import Base: ==, <, <=, -, +, *, /, ~,
trunc, round, floor, ceil, bswap,
div, fld, rem, mod, mod1, rem1, fld1, min, max,
start, next, done

abstract FixedPoint <: Real
abstract Fixed <: FixedPoint
abstract Ufixed <: FixedPoint # unsigned variant
# T => BaseType
# f => Number of Bytes reserved for fractional part
abstract FixedPoint{T <: Integer, f} <: Real

export
FixedPoint,
Fixed,
Ufixed,
Fixed32,
Ufixed8,
Ufixed10,
Ufixed12,
Ufixed14,
Ufixed16,
UFixed,
Fixed16,
UFixed8,
UFixed10,
UFixed12,
UFixed14,
UFixed16,
# constructors
ufixed8,
ufixed10,
Expand All @@ -43,10 +42,26 @@ export

reinterpret(x::FixedPoint) = x.i

include("fixed32.jl")
# 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

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

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}) = typemin(T)
realmax{T<: FixedPoint}(::Type{T}) = typemax(T)

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


for T in tuple(Fixed32, UF...)
# TODO: rewrite this by @generated
for T in tuple(Fixed16, UF...)
R = rawtype(T)
@eval begin
reinterpret(::Type{$R}, x::$T) = x.i
Expand Down
13 changes: 13 additions & 0 deletions src/deprecations.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Base.@deprecate_binding

@deprecate_binding UfixedBase UFixed
@deprecate_binding UfixedConstructor UFixedConstructor
@deprecate_binding Ufixed UFixed
@deprecate_binding Ufixed8 UFixed8
@deprecate_binding Ufixed10 UFixed10
@deprecate_binding Ufixed12 UFixed12
@deprecate_binding Ufixed14 UFixed14
@deprecate_binding Ufixed16 UFixed16

@deprecate_binding Fixed32 Fixed16
@deprecate Fixed(x::Real) convert(Fixed{Int32, 16}, x)
66 changes: 66 additions & 0 deletions src/fixed.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# 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,0)
convert{T,f}(::Type{Fixed{T,f}}, x::AbstractFloat) = Fixed{T,f}(trunc(T,x)<<f + round(T, 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{T,f}(::Type{BigFloat}, x::Fixed{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(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{TI<:Integer, T,f}(::Type{TI}, x::Fixed{T,f})
isinteger(x) || throw(InexactError())
convert(TI, x.i>>f)
end

convert{TR<:Rational,T,f}(::Type{TR}, x::Fixed{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}

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

# printing
function show(io::IO, x::Fixed)
print(io, typeof(x))
print(io, "(")
showcompact(io, x)
print(io, ")")
end
const _log2_10 = 3.321928094887362
showcompact{T,f}(io::IO, x::Fixed{T,f}) = show(io, round(convert(Float64,x), ceil(Int,f/_log2_10)))
73 changes: 0 additions & 73 deletions src/fixed32.jl

This file was deleted.

Loading