clash-prelude-0.7: CAES Language for Synchronous Hardware - Prelude library

Copyright(C) 2013-2015, University of Twente
LicenseBSD2 (see the file LICENSE)
MaintainerChristiaan Baaij <christiaan.baaij@gmail.com>
Safe HaskellNone
LanguageHaskell2010
Extensions
  • UndecidableInstances
  • MonoLocalBinds
  • TemplateHaskell
  • ScopedTypeVariables
  • TypeFamilies
  • ConstraintKinds
  • DataKinds
  • StandaloneDeriving
  • FlexibleContexts
  • MultiParamTypeClasses
  • KindSignatures
  • GeneralizedNewtypeDeriving
  • TypeOperators
  • ExplicitNamespaces
  • ExplicitForAll

CLaSH.Sized.Fixed

Contents

Description

Fixed point numbers

  • The Num operators for the given types saturate on overflow, and use truncation as the rounding method.
  • Fixed has an instance for Fractional meaning you use fractional literals (3.75 :: SFixed 4 18).
  • Both integer literals and fractional literals are clipped to minBound and maxBound.
  • There is no Floating instance for Fixed, but you can use $$(fLit d) to create Fixed point literal from Double constant at compile-time.
  • Use Constraint synonyms when writing type signatures for polymorphic functions that use Fixed point numbers.

BEWARE: rounding by truncation introduces a sign bias!

  • Truncation for positive numbers effectively results in: round towards zero.
  • Truncation for negative numbers effectively results in: round towards -infinity.

Synopsis

SFixed: Signed Fixed point numbers

type SFixed = Fixed Signed Source

Signed Fixed-point number, with int integer bits (including sign-bit) and frac fractional bits.

  • The range SFixed int frac numbers is: [-(2^(int -1)) .. 2^(int-1) - 2^-frac ]
  • The resolution of SFixed int frac numbers is: 2^frac
  • The Num operators for this type saturate on overflow, and use truncation as the rounding method.
>>> maxBound :: SFixed 3 4
3.9375
>>> minBound :: SFixed 3 4
-4.0
>>> 1  + 2 :: SFixed 3 4
3.0
>>> 2 + 3 :: SFixed 3 4
3.9375
>>> (-2) + (-3) :: SFixed 3 4
-4.0
>>> 1.375 * (-0.8125) :: SFixed 3 4
-1.125
>>> (1.375 :: SFixed 3 4) `times` (-0.8125 :: SFixed 3 4) :: SFixed 6 8
-1.1171875
>>> (2 :: SFixed 3 4) `plus` (3 :: SFixed 3 4) :: SFixed 4 4
5.0
>>> (-2 :: SFixed 3 4) `plus` (-3 :: SFixed 3 4) :: SFixed 4 4
-5.0

sf Source

Arguments

:: SNat frac

Position of the virtual point

-> Signed (int + frac)

The Signed integer

-> SFixed int frac 

Treat a Signed integer as a Signed Fixed-point integer

>>> sf d4 (-22 :: Signed 7)
-1.375

unSF :: SFixed int frac -> Signed (int + frac) Source

See the underlying representation of a Signed Fixed-point integer

UFixed: Unsigned Fixed point numbers

type UFixed = Fixed Unsigned Source

Unsigned Fixed-point number, with int integer bits and frac fractional bits

  • The range UFixed int frac numbers is: [0 .. 2^int - 2^-frac ]
  • The resolution of UFixed int frac numbers is: 2^frac
  • The Num operators for this type saturate on overflow, and use truncation as the rounding method.
>>> maxBound :: UFixed 3 4
7.9375
>>> minBound :: UFixed 3 4
0.0
>>> 1 + 2 :: UFixed 3 4
3.0
>>> 2 + 6 :: UFixed 3 4
7.9375
>>> 1 - 3 :: UFixed 3 4
0.0
>>> 1.375 * 0.8125 :: UFixed 3 4
1.0625
>>> (1.375 :: UFixed 3 4) `times` (0.8125 :: UFixed 3 4) :: UFixed 6 8
1.1171875
>>> (2 :: UFixed 3 4) `plus` (6 :: UFixed 3 4) :: UFixed 4 4
8.0

However, minus does not saturate to minBound on underflow:

>>> (1 :: UFixed 3 4) `minus` (3 :: UFixed 3 4) :: UFixed 4 4
14.0

uf Source

Arguments

:: SNat frac

Position of the virtual point

-> Unsigned (int + frac)

The Unsigned integer

-> UFixed int frac 

Treat an Unsigned integer as a Unsigned Fixed-point number

>>> uf d4 (92 :: Unsigned 7)
5.75

unUF :: UFixed int frac -> Unsigned (int + frac) Source

See the underlying representation of an Unsigned Fixed-point integer

Division

divide :: DivideC rep int1 frac1 int2 frac2 => Fixed rep int1 frac1 -> Fixed rep int2 frac2 -> Fixed rep ((int1 + frac2) + 1) (int2 + frac1) Source

Fixed point division

When used in a polymorphic setting, use the following Constraint synonyms for less verbose type signatures:

  • DivideC rep int1 frac1 int2 frac2 for: Fixed rep int1 frac1 -> Fixed rep int2 frac2 -> Fixed rep (int1 + frac2 + 1) (int2 + frac1)
  • DivideSC rep int1 frac1 int2 frac2 for: SFixed int1 frac1 -> SFixed int2 frac2 -> SFixed (int1 + frac2 + 1) (int2 + frac1)
  • DivideUC rep int1 frac1 int2 frac2 for: UFixed int1 frac1 -> UFixed int2 frac2 -> UFixed (int1 + frac2 + 1) (int2 + frac1)

Compile-time Double conversion

fLit :: forall rep int frac size. (size ~ (int + frac), KnownNat frac, Num (rep size), Bounded (rep size), Integral (rep size)) => Double -> Q (TExp (Fixed rep int frac)) Source

Convert, at compile-time, a Double constant to a Fixed-point literal. The conversion saturates on overflow, and uses truncation as its rounding method.

So when you type:

n = $$(fLit pi) :: SFixed 4 4

The compiler sees:

n = Fixed (fromInteger 50) :: SFixed 4 4

Upon evaluation you see that the value is rounded / truncated in accordance to the fixed point representation:

>>> n
3.125

Further examples:

>>> sin 0.5 :: Double
0.479425538604203
>>> $$(fLit (sin 0.5)) :: SFixed 1 8
0.4765625
>>> atan 0.2 :: Double
0.19739555984988078
>>> $$(fLit (atan 0.2)) :: SFixed 1 8
0.1953125
>>> $$(fLit (atan 0.2)) :: SFixed 1 20
0.19739532470703125

Fixed point wrapper

newtype Fixed rep int frac Source

Fixed-point number

Where:

  • rep is the underlying representation
  • int is the number of bits used to represent the integer part
  • frac is the number of bits used to represent the fractional part

The Num operators for this type saturate to maxBound on overflow and minBound on underflow, and use truncation as the rounding method.

Constructors

Fixed 

Fields

unFixed :: rep (int + frac)
 

Instances

Bounded (rep ((+) int frac)) => Bounded (Fixed rep int frac) 
Enum (rep ((+) int frac)) => Enum (Fixed rep int frac) 
Eq (rep ((+) int frac)) => Eq (Fixed rep int frac) 
FracFixedC rep int frac => Fractional (Fixed rep int frac)

The operators of this instance saturate on overflow, and use truncation as the rounding method.

When used in a polymorphic setting, use the following Constraint synonyms for less verbose type signatures:

NumFixedC rep int frac => Num (Fixed rep int frac)

The operators of this instance saturate on overflow, and use truncation as the rounding method.

When used in a polymorphic setting, use the following Constraint synonyms for less verbose type signatures:

Ord (rep ((+) int frac)) => Ord (Fixed rep int frac) 
((~) Nat size ((+) int frac), Show (rep size), Bits (rep size), KnownNat frac, Integral (rep size)) => Show (Fixed rep int frac) 
Bits (rep ((+) int frac)) => Bits (Fixed rep int frac) 
Default (rep ((+) int frac)) => Default (Fixed rep int frac) 
(Lift (rep ((+) int frac)), KnownNat frac, KnownNat int, Typeable (Nat -> *) rep) => Lift (Fixed rep int frac) 
NumFixedC rep int frac => SaturatingNum (Fixed rep int frac) 
BitPack (rep ((+) int frac)) => BitPack (Fixed rep int frac) 
Bundle (Fixed rep int frac) 
ENumFixedC rep int1 frac1 int2 frac2 => ExtendingNum (Fixed rep int1 frac1) (Fixed rep int2 frac2)

When used in a polymorphic setting, use the following Constraint synonyms for less verbose type signatures:

type Unbundled' clk (Fixed rep int frac) = Signal' clk (Fixed rep int frac) 
type BitSize (Fixed rep int frac) = BitSize (rep ((+) int frac)) 
type AResult (Fixed rep int1 frac1) (Fixed rep int2 frac2) = Fixed rep ((+) 1 (Max int1 int2)) (Max frac1 frac2) 
type MResult (Fixed rep int1 frac1) (Fixed rep int2 frac2) = Fixed rep ((+) int1 int2) ((+) frac1 frac2) 

resizeF :: (ResizeFC rep int1 frac1 int2 frac2, Bounded (rep (int2 + frac2))) => Fixed rep int1 frac1 -> Fixed rep int2 frac2 Source

Saturating resize operation, truncates for rounding

>>> 0.8125 :: SFixed 3 4
0.8125
>>> resizeF (0.8125 :: SFixed 3 4) :: SFixed 2 3
0.75
>>> 3.4 :: SFixed 3 4
3.375
>>> resizeF (3.4 :: SFixed 3 4) :: SFixed 2 3
1.875
>>> maxBound :: SFixed 2 3
1.875

When used in a polymorphic setting, use the following Constraint synonyms for less verbose type signatures:

fracShift :: KnownNat frac => Fixed rep int frac -> Int Source

Get the position of the virtual point of a Fixed-point number

Constraint synonyms

Writing polymorphic functions over fixed point numbers can be a potentially verbose due to the many class constraints induced by the functions and operators of this module.

Writing a simple multiply-and-accumulate function can already give rise to many lines of constraints:

mac :: ( KnownNat frac
       , KnownNat (frac + frac)
       , KnownNat (int + frac)
       , KnownNat (1 + (int + frac))
       , KnownNat ((int + frac) + (int + frac))
       , ((int + int) + (frac + frac)) ~ ((int + frac) + (int + frac))
       )
    => SFixed int frac
    -> SFixed int frac
    -> SFixed int frac
    -> SFixed int frac
mac s x y = s + (x * y)

But with constraint synonyms, you can write the type signature like this:

mac1 :: NumSFixedC int frac
    => SFixed int frac
    -> SFixed int frac
    -> SFixed int frac
    -> SFixed int frac
mac1 s x y = s + (x * y)

Where NumSFixedC refers to the Constraints needed by the operators of the Num class for the SFixed datatype.

Although the number of constraints for the mac function defined earlier might be considered small, here is an "this way lies madness" example where you really want to use constraint kinds:

mac2 :: ( KnownNat frac1
        , KnownNat frac2
        , KnownNat frac3
        , KnownNat (Max frac1 frac2)
        , KnownNat (int1 + frac1)
        , KnownNat (int2 + frac2)
        , KnownNat (int3 + frac3)
        , KnownNat (frac1 + frac2)
        , KnownNat (Max (frac1 + frac2) frac3)
        , KnownNat (((int1 + int2) + (frac1 + frac2)) + (int3 + frac3))
        , KnownNat ((int1 + int2) + (frac1 + frac2))
        , KnownNat (1 + Max (int1 + frac1) (int2 + frac2))
        , KnownNat (1 + Max (int1 + int2) int3 + Max (frac1 + frac2) frac3)
        , KnownNat ((1 + Max int1 int2) + Max frac1 frac2)
        , KnownNat ((1 + Max ((int1 + int2) + (frac1 + frac2)) (int3 + frac3)))
        , ((int1 + frac1) + (int2 + frac2)) ~ ((int1 + int2) + (frac1 + frac2))
        , (((int1 + int2) + int3) + ((frac1 + frac2) + frac3)) ~ (((int1 + int2) + (frac1 + frac2)) + (int3 + frac3))
        )
     => SFixed int1 frac1
     -> SFixed int2 frac2
     -> SFixed int3 frac3
     -> SFixed (1 + Max (int1 + int2) int3) (Max (frac1 + frac2) frac3)
mac2 x y s = (x `times` y) `plus` s

Which, with the proper constraint kinds can be reduced to:

mac3 :: ( ENumSFixedC int1 frac1 int2 frac2
        , ENumSFixedC (int1 + int2) (frac1 + frac2) int3 frac3
        )
     => SFixed int1 frac1
     -> SFixed int2 frac2
     -> SFixed int3 frac3
     -> SFixed (1 + Max (int1 + int2) int3) (Max (frac1 + frac2) frac3)
mac3 x y s = (x `times` y) `plus` s

Constraint synonyms for SFixed

type NumSFixedC int frac = (KnownNat frac, KnownNat (frac + frac), KnownNat (int + frac), KnownNat (1 + (int + frac)), KnownNat ((int + frac) + (int + frac)), ((int + int) + (frac + frac)) ~ ((int + frac) + (int + frac))) Source

Constraint for the Num instance of SFixed

type ENumSFixedC int1 frac1 int2 frac2 = (KnownNat frac1, KnownNat frac2, KnownNat (Max frac1 frac2), KnownNat (int1 + frac1), KnownNat (int2 + frac2), KnownNat ((int1 + int2) + (frac1 + frac2)), KnownNat (1 + Max (int1 + frac1) (int2 + frac2)), KnownNat ((1 + Max int1 int2) + Max frac1 frac2), ((int1 + frac1) + (int2 + frac2)) ~ ((int1 + int2) + (frac1 + frac2))) Source

Constraint for the ExtendingNum instance of SFixed

type FracSFixedC int frac = (NumSFixedC int frac, KnownNat int, KnownNat (((int + frac) + 1) + (int + frac))) Source

Constraint for the Fractional instance of SFixed

type ResizeSFC int1 frac1 int2 frac2 = (KnownNat frac1, KnownNat frac2, KnownNat (int1 + frac1), KnownNat (int2 + frac2)) Source

Constraint for the resizeF function, specialized for SFixed

type DivideSC int1 frac1 int2 frac2 = (KnownNat int2, KnownNat frac2, KnownNat (int1 + frac1), KnownNat (int2 + frac2), KnownNat (((int1 + frac2) + 1) + (int2 + frac1))) Source

Constraint for the divide function, specialized for SFixed

Constraint synonyms for UFixed

type NumUFixedC int frac = NumSFixedC int frac Source

Constraint for the Num instance of UFixed

type ENumUFixedC int1 frac1 int2 frac2 = ENumSFixedC int1 frac1 int2 frac2 Source

Constraint for the ExtendingNum instance of UFixed

type FracUFixedC int frac = FracSFixedC int frac Source

Constraint for the Fractional instance of UFixed

type ResizeUFC int1 frac1 int2 frac2 = ResizeSFC int1 frac1 int2 frac2 Source

Constraint for the resizeF function, specialized for UFixed

type DivideUC int1 frac1 int2 frac2 = DivideSC int1 frac1 int2 frac2 Source

Constraint for the divide function, specialized for UFixed

Constraint synonyms for Fixed wrapper

type NumFixedC rep int frac = (SaturatingNum (rep (int + frac)), ExtendingNum (rep (int + frac)) (rep (int + frac)), ResizeFC rep (int + int) (frac + frac) int frac, MResult (rep (int + frac)) (rep (int + frac)) ~ rep ((int + int) + (frac + frac))) Source

Constraint for the Num instance of Fixed

type ENumFixedC rep int1 frac1 int2 frac2 = (ResizeFC rep int1 frac1 (1 + Max int1 int2) (Max frac1 frac2), ResizeFC rep int2 frac2 (1 + Max int1 int2) (Max frac1 frac2), Bounded (rep ((1 + Max int1 int2) + Max frac1 frac2)), Num (rep ((1 + Max int1 int2) + Max frac1 frac2)), ExtendingNum (rep (int1 + frac1)) (rep (int2 + frac2)), MResult (rep (int1 + frac1)) (rep (int2 + frac2)) ~ rep ((int1 + int2) + (frac1 + frac2))) Source

Constraint for the ExtendingNum instance of Fixed

type FracFixedC rep int frac = (NumFixedC rep int frac, DivideC rep int frac int frac, Integral (rep (int + frac))) Source

Constraint for the Fractional instance of Fixed

type ResizeFC rep int1 frac1 int2 frac2 = (Resize rep, Ord (rep (int1 + frac1)), Num (rep (int1 + frac1)), Bits (rep (int1 + frac1)), Bits (rep (int2 + frac2)), KnownNat frac1, KnownNat frac2, KnownNat (int1 + frac1), KnownNat (int2 + frac2)) Source

Constraint for the resizeF function

type DivideC rep int1 frac1 int2 frac2 = (Resize rep, Integral (rep (((int1 + frac2) + 1) + (int2 + frac1))), Bits (rep (((int1 + frac2) + 1) + (int2 + frac1))), KnownNat int2, KnownNat frac2, KnownNat (int1 + frac1), KnownNat (int2 + frac2), KnownNat (((int1 + frac2) + 1) + (int2 + frac1))) Source

Constraint for the divide function

Proxy

asRepProxy :: Fixed rep int frac -> Proxy rep Source

asIntProxy :: Fixed rep int frac -> Proxy int Source