This library implements fixed-point number types. A fixed-point number represents a fractional, or non-integral, number. In contrast with the more widely known floating-point numbers, with fixed-point numbers the decimal point doesn't "float": fixed-point numbers are effectively integers that are interpreted as being scaled by a constant factor. Consequently, they have a fixed number of digits (bits) after the decimal (radix) point.

Fixed-point numbers can be used to perform arithmetic. Another practical application is to implicitly rescale integers without modifying the underlying representation.

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 some cases these operations result in conversion to floating-point types.

This library defines an abstract type `FixedPoint{T <: Integer, f}`

as a
subtype of `Real`

. The parameter `T`

is the underlying machine representation and `f`

is the number of fraction bits.

For `T<:Signed`

(a signed integer), there is a fixed-point type
`Fixed{T, f}`

; for `T<:Unsigned`

(an unsigned integer), there is the
`Normed{T, f}`

type. However, there are slight differences in behavior
that go beyond signed/unsigned distinctions.

The `Fixed{T,f}`

types use 1 bit for sign, and `f`

bits to represent
the fraction. For example, `Fixed{Int8,7}`

uses 7 bits (all bits
except the sign bit) for the fractional part. The value of the number
is interpreted as if the integer representation has been divided by
`2^f`

. Consequently, `Fixed{Int8,7}`

numbers `x`

satisfy

```
-1.0 = -128/128 ≤ x ≤ 127/128 ≈ 0.992.
```

because the range of `Int8`

is from -128 to 127.

In contrast, the `Normed{T,f}`

, with `f`

fraction bits, map the closed
interval [0.0,1.0] to the span of numbers with `f`

bits. For example,
the `N0f8`

type (aliased to `Normed{UInt8,8}`

) is represented
internally by a `UInt8`

, and makes `0x00`

equivalent to `0.0`

and
`0xff`

to `1.0`

. Consequently, `Normed`

numbers are scaled by `2^f-1`

rather than `2^f`

. The type aliases `N6f10`

, `N4f12`

,
`N2f14`

, and `N0f16`

are all based on `UInt16`

and reach the
value `1.0`

at 10, 12, 14, and 16 bits, respectively (`0x03ff`

,
`0x0fff`

, `0x3fff`

, and `0xffff`

). The `NXfY`

notation is used for
compact printing and the `fY`

component informs about the number of
fractional bits and `X+Y`

equals the number of underlying bits used.

To construct such a number, use `convert(N4f12, 1.3)`

, `N4f12(1.3)`

,
`Normed{UInt16,12}(1.3)`

, or `reinterpret(N4f12, 0x14cc)`

.
The latter syntax means to construct a `N4f12`

(it ends in
`uf12`

) from the `UInt16`

value `0x14cc`

.

More generally, an arbitrary number of bits from any of the standard unsigned
integer widths can be used for the fractional part. For example:
`Normed{UInt32,16}`

, `Normed{UInt64,3}`

, `Normed{UInt128,7}`

.

02/27/2014

4 months ago

166 commits