clash-prelude-1.8.4: Clash: a functional hardware description language - Prelude library

Copyright | (C) 2013-2016 University of Twente 2021 QBayLogic B.V.
License | BSD2 (see the file LICENSE)
Maintainer | QBayLogic B.V. <devops@qbaylogic.com>
Safe Haskell | Trustworthy
Language | Haskell2010

Extensions

- Cpp
- UndecidableInstances
- MonoLocalBinds
- TemplateHaskell
- TemplateHaskellQuotes
- ScopedTypeVariables
- BangPatterns
- TypeFamilies
- ViewPatterns
- ConstraintKinds
- DataKinds
- InstanceSigs
- StandaloneDeriving
- DeriveDataTypeable
- DeriveFunctor
- DeriveTraversable
- DeriveFoldable
- DeriveGeneric
- DefaultSignatures
- DeriveLift
- DerivingStrategies
- FlexibleContexts
- ConstrainedClassMethods
- MultiParamTypeClasses
- MagicHash
- KindSignatures
- GeneralizedNewtypeDeriving
- PostfixOperators
- TupleSections
- TypeOperators
- ExplicitNamespaces
- ExplicitForAll
- BinaryLiterals
- NegativeLiterals
- TypeApplications

Clash.Sized.Fixed

Contents

- `SFixed`: `Signed` `Fixed` point numbers
- `UFixed`: `Unsigned` `Fixed` point numbers
- Division
- Compile-time `Double` conversion
- Run-time `Double` conversion (not synthesizable)
- `Fixed` point wrapper
- Constraint synonyms
  - Constraint synonyms for `SFixed`
  - Constraint synonyms for `UFixed`
  - Constraint synonyms for `Fixed` wrapper
- Proxy

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`. NB: Needs the `-XNegativeLiterals` language extension to work for signed numbers.
- 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 can introduce errors larger than naively assumed; e.g. for Fixed 16 1, rounding by truncation turns the real number 4.99 to 4.5, not 5.0, i.e. an error or 0.49 instead of 0.01

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.

## Reasoning about precision

Givens the real numbers A and B, and the corresponding fixed point numbers FA+-da and FB+db, where da and db denote the (potential) error introduced by truncation w.r.t. the original A and B, the arithmetic operators on fixed point numbers have the following error propagation properties:

- Addition: da + db
- Subtraction: da - db
- Multiplication: FA*db + FB*da + da*db
- Division: (FA+da)/(FB+db) - FA/FB

### Additional error from truncation

Given:

    >>> 4.13 :: UFixed 16 3
    4.125
    >>> 20.9 :: UFixed 16 3
    20.875

The expected error that we would get from multiplication is: 20.875*0.005 + 4.125*0.025 + 0.025*0.005 = 0.207625

    >>> 4.13 * 20.9 :: Double
    86.317
    >>> (4.13 :: UFixed 16 3) `mul` (20.9 :: UFixed 16 3) :: UFixed 32 6
    86.109375
    >>> 86.109375 + 0.207625 :: Double
    86.317

However the 0.109375 is smaller than 2^-3, so the regular multiplication operator that uses truncation introduces an additional error of 0.109375:

    >>> (4.13 :: UFixed 16 3) * (20.9 :: UFixed 16 3) :: UFixed 16 3
    86.0

Synopsis

- type SFixed = Fixed Signed
- sf :: forall (frac :: Nat) (int :: Natural). SNat frac -> Signed (int + frac) -> SFixed int frac
- unSF :: forall (int :: Nat) (frac :: Nat). SFixed int frac -> Signed (int + frac)
- type UFixed = Fixed Unsigned
- uf :: forall (frac :: Nat) (int :: Natural). SNat frac -> Unsigned (int + frac) -> UFixed int frac
- unUF :: forall (int :: Nat) (frac :: Nat). UFixed int frac -> Unsigned (int + frac)
- divide :: forall (rep :: Nat -> Type) (int1 :: Natural) (frac1 :: Natural) (int2 :: Natural) (frac2 :: Natural). DivideC rep int1 frac1 int2 frac2 => Fixed rep int1 frac1 -> Fixed rep int2 frac2 -> Fixed rep ((int1 + frac2) + 1) (int2 + frac1)
- fLit :: forall (rep :: Natural -> Type) (int :: Natural) (frac :: Natural) (size :: Natural). (size ~ (int + frac), KnownNat frac, Bounded (rep size), Integral (rep size)) => Double -> Code Q (Fixed rep int frac)
- fLitR :: forall (rep :: Natural -> Type) (int :: Natural) (frac :: Natural) (size :: Natural). (size ~ (int + frac), KnownNat frac, Bounded (rep size), Integral (rep size)) => Double -> Fixed rep int frac
- newtype Fixed (rep :: Nat -> Type) (int :: Nat) (frac :: Nat) = Fixed {
  - unFixed :: rep (int + frac)
  }
- resizeF :: forall (rep :: Nat -> Type) (int1 :: Natural) (frac1 :: Natural) (int2 :: Natural) (frac2 :: Natural). ResizeFC rep int1 frac1 int2 frac2 => Fixed rep int1 frac1 -> Fixed rep int2 frac2
- fracShift :: forall (frac :: Nat) (rep :: Nat -> Type) (int :: Nat). KnownNat frac => Fixed rep int frac -> Int
- type NumSFixedC (int :: Natural) (frac :: Natural) = (KnownNat ((int + int) + (frac + frac)), KnownNat (frac + frac), KnownNat (int + int), KnownNat (int + frac), KnownNat frac, KnownNat int)
- type ENumSFixedC (int1 :: Nat) (frac1 :: Nat) (int2 :: Natural) (frac2 :: Natural) = (KnownNat (int2 + frac2), KnownNat ((1 + Max int1 int2) + Max frac1 frac2), KnownNat (Max frac1 frac2), KnownNat (1 + Max int1 int2), KnownNat (int1 + frac1), KnownNat frac2, KnownNat int2, KnownNat frac1, KnownNat int1)
- type FracSFixedC (int :: Natural) (frac :: Natural) = (NumSFixedC int frac, KnownNat (((int + frac) + 1) + (int + frac)))
- type ResizeSFC (int1 :: Nat) (frac1 :: Nat) (int2 :: Nat) (frac2 :: Nat) = (KnownNat int1, KnownNat frac1, KnownNat int2, KnownNat frac2, KnownNat (int2 + frac2), KnownNat (int1 + frac1))
- type DivideSC (int1 :: Natural) (frac1 :: Natural) (int2 :: Natural) (frac2 :: Natural) = (KnownNat (((int1 + frac2) + 1) + (int2 + frac1)), KnownNat frac2, KnownNat int2, KnownNat frac1, KnownNat int1)
- type NumUFixedC (int :: Natural) (frac :: Natural) = NumSFixedC int frac
- type ENumUFixedC (int1 :: Nat) (frac1 :: Nat) (int2 :: Natural) (frac2 :: Natural) = ENumSFixedC int1 frac1 int2 frac2
- type FracUFixedC (int :: Natural) (frac :: Natural) = FracSFixedC int frac
- type ResizeUFC (int1 :: Nat) (frac1 :: Nat) (int2 :: Nat) (frac2 :: Nat) = ResizeSFC int1 frac1 int2 frac2
- type DivideUC (int1 :: Natural) (frac1 :: Natural) (int2 :: Natural) (frac2 :: Natural) = DivideSC int1 frac1 int2 frac2
- type NumFixedC (rep :: Natural -> Type) (int :: Natural) (frac :: Natural) = (SaturatingNum (rep (int + frac)), ExtendingNum (rep (int + frac)) (rep (int + frac)), MResult (rep (int + frac)) (rep (int + frac)) ~ rep ((int + int) + (frac + frac)), BitSize (rep ((int + int) + (frac + frac))) ~ (int + ((int + frac) + frac)), BitPack (rep ((int + int) + (frac + frac))), Bits (rep ((int + int) + (frac + frac))), BitPack (rep (int + frac)), Bits (rep (int + frac)), Integral (rep (int + frac)), Resize rep, Typeable rep, KnownNat int, KnownNat frac)
- type ENumFixedC (rep :: Natural -> Type) (int1 :: Nat) (frac1 :: Nat) (int2 :: Nat) (frac2 :: Nat) = (Bounded (rep ((1 + Max int1 int2) + Max frac1 frac2)), Num (rep ((1 + Max int1 int2) + Max frac1 frac2)), Bits (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)), KnownNat int1, KnownNat int2, KnownNat frac1, KnownNat frac2, Resize rep)
- type FracFixedC (rep :: Natural -> Type) (int :: Natural) (frac :: Natural) = (NumFixedC rep int frac, DivideC rep int frac int frac)
- type ResizeFC (rep :: Nat -> Type) (int1 :: Natural) (frac1 :: Natural) (int2 :: Natural) (frac2 :: Natural) = (Resize rep, Ord (rep (int1 + frac1)), Num (rep (int1 + frac1)), Bits (rep (int1 + frac1)), Bits (rep (int2 + frac2)), Bounded (rep (int2 + frac2)), KnownNat int1, KnownNat frac1, KnownNat int2, KnownNat frac2)
- type DivideC (rep :: Nat -> Type) (int1 :: Natural) (frac1 :: Natural) (int2 :: Natural) (frac2 :: Natural) = (Resize rep, Integral (rep (((int1 + frac2) + 1) + (int2 + frac1))), Bits (rep (((int1 + frac2) + 1) + (int2 + frac1))), KnownNat int1, KnownNat frac1, KnownNat int2, KnownNat frac2)
- asRepProxy :: forall (rep :: Nat -> Type) (int :: Nat) (frac :: Nat). Fixed rep int frac -> Proxy rep
- asIntProxy :: forall (rep :: Nat -> Type) (int :: Nat) (frac :: Nat). Fixed rep int frac -> Proxy int

# `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
    >>> read (show (maxBound :: SFixed 3 4)) :: SFixed 3 4
    3.9375
    >>> 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) `mul` (-0.8125 :: SFixed 3 4) :: SFixed 6 8
    -1.1171875
    >>> (2 :: SFixed 3 4) `add` (3 :: SFixed 3 4) :: SFixed 4 4
    5.0
    >>> (-2 :: SFixed 3 4) `add` (-3 :: SFixed 3 4) :: SFixed 4 4
    -5.0

sf Source #

Arguments

:: forall (frac :: Nat) (int :: Natural). 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 :: forall (int :: Nat) (frac :: Nat). 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) `mul` (0.8125 :: UFixed 3 4) :: UFixed 6 8
    1.1171875
    >>> (2 :: UFixed 3 4) `add` (6 :: UFixed 3 4) :: UFixed 4 4
    8.0

However, `sub` does not saturate to `minBound` on underflow:

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

uf Source #

Arguments

:: forall (frac :: Nat) (int :: Natural). 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 :: forall (int :: Nat) (frac :: Nat). UFixed int frac -> Unsigned (int + frac) Source #

See the underlying representation of an Unsigned Fixed-point integer

# Division

divide :: forall (rep :: Nat -> Type) (int1 :: Natural) (frac1 :: Natural) (int2 :: Natural) (frac2 :: Natural). 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 :: Natural -> Type) (int :: Natural) (frac :: Natural) (size :: Natural). (size ~ (int + frac), KnownNat frac, Bounded (rep size), Integral (rep size)) => Double -> Code Q (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

# Run-time `Double` conversion (not synthesizable)

fLitR :: forall (rep :: Natural -> Type) (int :: Natural) (frac :: Natural) (size :: Natural). (size ~ (int + frac), KnownNat frac, Bounded (rep size), Integral (rep size)) => Double -> Fixed rep int frac Source #

Convert, at run-time, a `Double` to a `Fixed`-point.

NB: This function is not synthesizable

# Creating data-files

An example usage of this function is to convert a data file containing `Double`s to a data file with ASCII-encoded binary numbers to be used by a synthesizable function like `asyncRomFile`. For example, consider a file `Data.txt` containing:

    1.2 2.0 3.0 4.0
    -1.0 -2.0 -3.5 -4.0

which we want to put in a ROM, interpreting them as `8.8` signed fixed point numbers. What we do is that we first create a conversion utility, `createRomFile`, which uses `fLitR`:

`createRomFile.hs`:

    module Main where

    import Clash.Prelude
    import Clash.Prelude.ROM.File
    import System.Environment
    import qualified Data.List as L

    createRomFile
      :: BitPack a
      => (Double -> a)
      -> FilePath
      -> FilePath
      -> IO ()
    createRomFile convert fileR fileW = do
      f <- readFile fileR
      let ds :: [Double]
          ds = L.concat . (L.map . L.map) read . L.map words $ lines f
          fes = L.map convert ds
      writeFile fileW (memFile Nothing fes)

    toSFixed8_8 :: Double -> SFixed 8 8
    toSFixed8_8 = fLitR

    main :: IO ()
    main = do
      [fileR,fileW] <- getArgs
      createRomFile toSFixed8_8 fileR fileW

We then compile this to an executable:

    $ clash --make createRomFile.hs

We can then use this utility to convert our `Data.txt` file which contains `Double`s to a `Data.bin` file which will containing the desired ASCII-encoded binary data:

    $ ./createRomFile Data.txt Data.bin

Which results in a `Data.bin` file containing:

    0000000100110011
    0000001000000000
    0000001100000000
    0000010000000000
    1111111100000000
    1111111000000000
    1111110010000000
    1111110000000000

We can then use this `Data.bin` file in for our ROM:

    romF :: Unsigned 3 -> Unsigned 3 -> SFixed 8 8
    romF rowAddr colAddr = unpack
                         $ asyncRomFile d8 "Data.bin" ((rowAddr * 4) + colAddr)

And see that it works as expected:

    >>> romF 1 2
    -3.5
    >>> romF 0 0
    1.19921875

## Using Template Haskell

For those of us who like to live on the edge, another option is to convert our `Data.txt` at compile-time using Template Haskell. For this we first create a module `CreateRomFileTH.hs`:

    module CreateRomFileTH (romDataFromFile) where

    import Clash.Prelude
    import Clash.Prelude.ROM.File
    import qualified Data.List as L
    import Language.Haskell.TH (ExpQ, litE, stringL)
    import Language.Haskell.TH.Syntax (qRunIO)

    createRomFile :: BitPack a => (Double -> a)
                  -> FilePath -> FilePath -> IO ()
    createRomFile convert fileR fileW = do
      f <- readFile fileR
      let ds :: [Double]
          ds = L.concat . (L.map . L.map) read . L.map words $ lines f
          fes = L.map convert ds
      writeFile fileW (memFile Nothing fes)

    romDataFromFile :: BitPack a => (Double -> a) -> String -> ExpQ
    romDataFromFile convert fileR = do
      let fileW = fileR L.++ ".bin"
      qRunIO (createRomFile convert fileR fileW)
      litE (stringL fileW)

Instead of first converting `Data.txt` to `Data.bin`, we will now use the `romDataFromFile` function to convert `Data.txt` to a new file in the proper format at compile-time of our new `romF'` function:

    import Clash.Prelude
    import CreateRomFileTH

    romF' :: Unsigned 3 -> Unsigned 3 -> SFixed 8 8
    romF' rowAddr colAddr = unpack $
      asyncRomFile d8
                   $(romDataFromFile (fLitR :: Double -> SFixed 8 8) "Data.txt") -- Template Haskell splice
                   ((rowAddr * 4) + colAddr)

And see that it works just like the `romF` function from earlier:

    >>> romF' 1 2
    -3.5
    >>> romF' 0 0
    1.19921875

# `Fixed` point wrapper

newtype Fixed (rep :: Nat -> Type) (int :: Nat) (frac :: Nat) 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.

Fixed has the type role

    >>> :i Fixed
    type role Fixed representational nominal nominal
    ...

as it is safe to coerce between different compatible underlying types, but not necessasrily safe to coerce between different widths of this type. To change the width, use the functions in the `Resize` class.

Constructors

Fixed |

Fields

- unFixed :: rep (int + frac)

#### Instances

Instances details

(Lift (rep (int + frac)), KnownNat frac, KnownNat int, Typeable rep) => Lift (Fixed rep int frac :: Type) Source # |
Instance details Defined in Clash.Sized.Fixed Methods lift :: Quote m => Fixed rep int frac -> m Exp Source # liftTyped :: forall (m :: Type -> Type). Quote m => Fixed rep int frac -> Code m (Fixed rep int frac) Source #
Arbitrary (rep (int + frac)) => Arbitrary (Fixed rep int frac) Source # |
Instance details Defined in Clash.Sized.Fixed Methods arbitrary :: Gen (Fixed rep int frac) Source # shrink :: Fixed rep int frac -> [Fixed rep int frac] Source #
CoArbitrary (rep (int + frac)) => CoArbitrary (Fixed rep int frac) Source # |
Instance details Defined in Clash.Sized.Fixed Methods coarbitrary :: Fixed rep int frac -> Gen b -> Gen b Source #
NFDataX (rep (int + frac)) => AutoReg (Fixed rep int frac) Source # |
Instance details Defined in Clash.Class.AutoReg.Internal Methods autoReg :: forall (dom :: Domain). (HasCallStack, KnownDomain dom) => Clock dom -> Reset dom -> Enable dom -> Fixed rep int frac -> Signal dom (Fixed rep int frac) -> Signal dom (Fixed rep int frac) Source #
(BitPack (rep (int + frac)), KnownNat (BitSize (rep (int + frac)))) => BitPack (Fixed rep int frac) Source # |

Instance details

Defined in Clash.Sized.Fixed

Associated Types

type BitSize (Fixed rep int frac) |
Instance details Defined in Clash.Sized.Fixed type BitSize (Fixed rep int frac) = BitSize (rep (int + frac))

Methods

pack :: Fixed rep int frac -> BitVector (BitSize (Fixed rep int frac)) Source #

unpack :: BitVector (BitSize (Fixed rep int frac)) -> Fixed rep int frac Source #

NumFixedC rep int frac => SaturatingNum (Fixed rep int frac) Source # |

Instance details

Defined in Clash.Sized.Fixed

Methods

satAdd :: SaturationMode -> Fixed rep int frac -> Fixed rep int frac -> Fixed rep int frac Source #

satSub :: SaturationMode -> Fixed rep int frac -> Fixed rep int frac -> Fixed rep int frac Source #

satMul :: SaturationMode -> Fixed rep int frac -> Fixed rep int frac -> Fixed rep int frac Source #

satSucc :: SaturationMode -> Fixed rep int frac -> Fixed rep int frac Source #

satPred :: SaturationMode -> Fixed rep int frac -> Fixed rep int frac Source #

Bundle (Fixed rep int frac) Source # |
Instance details Defined in Clash.Signal.Bundle Methods bundle :: forall (dom :: Domain). Unbundled dom (Fixed rep int frac) -> Signal dom (Fixed rep int frac) Source # unbundle :: forall (dom :: Domain). Signal dom (Fixed rep int frac) -> Unbundled dom (Fixed rep int frac) Source #
Bundle (Fixed rep int frac) Source # |
Instance details Defined in Clash.Signal.Delayed.Bundle Methods bundle :: forall (dom :: Domain) (d :: Nat). Unbundled dom d (Fixed rep int frac) -> DSignal dom d (Fixed rep int frac) Source # unbundle :: forall (dom :: Domain) (d :: Nat). DSignal dom d (Fixed rep int frac) -> Unbundled dom d (Fixed rep int frac) Source #
NFDataX (rep (int + frac)) => NFDataX (Fixed rep int frac) Source # |
Instance details Defined in Clash.Sized.Fixed Methods deepErrorX :: String -> Fixed rep int frac Source # hasUndefined :: Fixed rep int frac -> Bool Source # ensureSpine :: Fixed rep int frac -> Fixed rep int frac Source # rnfX :: Fixed rep int frac -> () Source #
(size ~ (int + frac), KnownNat frac, Integral (rep size)) => ShowX (Fixed rep int frac) Source # |
Instance details Defined in Clash.Sized.Fixed Methods showsPrecX :: Int -> Fixed rep int frac -> ShowS Source # showX :: Fixed rep int frac -> String Source # showListX :: [Fixed rep int frac] -> ShowS Source #
Default (rep (int + frac)) => Default (Fixed rep int frac) Source # |
Instance details Defined in Clash.Sized.Fixed Methods def :: Fixed rep int frac #
NFData (rep (int + frac)) => NFData (Fixed rep int frac) Source # |
Instance details Defined in Clash.Sized.Fixed Methods rnf :: Fixed rep int frac -> () Source #
Bits (rep (int + frac)) => Bits (Fixed rep int frac) Source # | Instance functions do not saturate. Meaning that "``shiftL` 1 == `satMul` `SatWrap` 2'`"

Instance details

Defined in Clash.Sized.Fixed

Methods

(.&.) :: Fixed rep int frac -> Fixed rep int frac -> Fixed rep int frac Source #

(.|.) :: Fixed rep int frac -> Fixed rep int frac -> Fixed rep int frac Source #

xor :: Fixed rep int frac -> Fixed rep int frac -> Fixed rep int frac Source #

complement :: Fixed rep int frac -> Fixed rep int frac Source #

shift :: Fixed rep int frac -> Int -> Fixed rep int frac Source #

rotate :: Fixed rep int frac -> Int -> Fixed rep int frac Source #

zeroBits :: Fixed rep int frac Source #

bit :: Int -> Fixed rep int frac Source #

setBit :: Fixed rep int frac -> Int -> Fixed rep int frac Source #

clearBit :: Fixed rep int frac -> Int -> Fixed rep int frac Source #

complementBit :: Fixed rep int frac -> Int -> Fixed rep int frac Source #

testBit :: Fixed rep int frac -> Int -> Bool Source #

bitSizeMaybe :: Fixed rep int frac -> Maybe Int Source #

bitSize :: Fixed rep int frac -> Int Source #

isSigned :: Fixed rep int frac -> Bool Source #

shiftL :: Fixed rep int frac -> Int -> Fixed rep int frac Source #

unsafeShiftL :: Fixed rep int frac -> Int -> Fixed rep int frac Source #

shiftR :: Fixed rep int frac -> Int -> Fixed rep int frac Source #

unsafeShiftR :: Fixed rep int frac -> Int -> Fixed rep int frac Source #

rotateL :: Fixed rep int frac -> Int -> Fixed rep int frac Source #

rotateR :: Fixed rep int frac -> Int -> Fixed rep int frac Source #

popCount :: Fixed rep int frac -> Int Source #

FiniteBits (rep (int + frac)) => FiniteBits (Fixed rep int frac) Source # |
Instance details Defined in Clash.Sized.Fixed Methods finiteBitSize :: Fixed rep int frac -> Int Source # countLeadingZeros :: Fixed rep int frac -> Int Source # countTrailingZeros :: Fixed rep int frac -> Int Source #
(Typeable rep, Typeable int, Typeable frac, Data (rep (int + frac))) => Data (Fixed rep int frac) Source # |

Instance details

Defined in Clash.Sized.Fixed

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Fixed rep int frac -> c (Fixed rep int frac) Source #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Fixed rep int frac) Source #

toConstr :: Fixed rep int frac -> Constr Source #

dataTypeOf :: Fixed rep int frac -> DataType Source #

dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (Fixed rep int frac)) Source #

dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Fixed rep int frac)) Source #

gmapT :: (forall b. Data b => b -> b) -> Fixed rep int frac -> Fixed rep int frac Source #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Fixed rep int frac -> r Source #

gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Fixed rep int frac -> r Source #

gmapQ :: (forall d. Data d => d -> u) -> Fixed rep int frac -> [u] Source #

gmapQi :: Int -> (forall d. Data d => d -> u) -> Fixed rep int frac -> u Source #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> Fixed rep int frac -> m (Fixed rep int frac) Source #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Fixed rep int frac -> m (Fixed rep int frac) Source #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Fixed rep int frac -> m (Fixed rep int frac) Source #

Bounded (rep (int + frac)) => Bounded (Fixed rep int frac) Source # |
Instance details Defined in Clash.Sized.Fixed Methods minBound :: Fixed rep int frac Source # maxBound :: Fixed rep int frac Source #

NumFixedC rep int frac => Enum (Fixed rep int frac) Source #

These behave similar to `Float`, `Double` and `Rational`. `succ`/`pred` add/subtract 1. See the Haskell Report for full details.

The rules set out there for instances of both `Enum` and `Bounded` are also observed. In particular, `succ` and `pred` result in a runtime error if the result cannot be represented. See `satSucc` and `satPred` for other options.

Instance details

Defined in Clash.Sized.Fixed

Methods

succ :: Fixed rep int frac -> Fixed rep int frac Source #

pred :: Fixed rep int frac -> Fixed rep int frac Source #

toEnum :: Int -> Fixed rep int frac Source #

fromEnum :: Fixed rep int frac -> Int Source #

enumFrom :: Fixed rep int frac -> [Fixed rep int frac] Source #

enumFromThen :: Fixed rep int frac -> Fixed rep int frac -> [Fixed rep int frac] Source #

enumFromTo :: Fixed rep int frac -> Fixed rep int frac -> [Fixed rep int frac] Source #

enumFromThenTo :: Fixed rep int frac -> Fixed rep int frac -> Fixed rep int frac -> [Fixed rep int frac] Source #

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

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` frac rep size` for: ``Fixed` frac rep size`
- ``NumSFixedC` int frac` for: ``SFixed` int frac`
- ``NumUFixedC` int frac` for: ``UFixed` int frac`

Instance details

Defined in Clash.Sized.Fixed

Methods

(+) :: Fixed rep int frac -> Fixed rep int frac -> Fixed rep int frac Source #

(-) :: Fixed rep int frac -> Fixed rep int frac -> Fixed rep int frac Source #

(*) :: Fixed rep int frac -> Fixed rep int frac -> Fixed rep int frac Source #

negate :: Fixed rep int frac -> Fixed rep int frac Source #

abs :: Fixed rep int frac -> Fixed rep int frac Source #

signum :: Fixed rep int frac -> Fixed rep int frac Source #

fromInteger :: Integer -> Fixed rep int frac Source #

(size ~ (int + frac), KnownNat frac, Bounded (rep size), Integral (rep size)) => Read (Fixed rep int frac) Source # | None of the `Read` class' methods are synthesizable.
Instance details Defined in Clash.Sized.Fixed Methods readsPrec :: Int -> ReadS (Fixed rep int frac) Source # readList :: ReadS [Fixed rep int frac] Source # readPrec :: ReadPrec (Fixed rep int frac) Source # readListPrec :: ReadPrec [Fixed rep int frac] Source #

FracFixedC rep int frac => Fractional (Fixed rep int frac) Source #

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:

- ``FracFixedC` frac rep size` for: ``Fixed` frac rep size`
- ``FracSFixedC` int frac` for: ``SFixed` int frac`
- ``FracUFixedC` int frac` for: ``UFixed` int frac`

Instance details Defined in Clash.Sized.Fixed Methods (/) :: Fixed rep int frac -> Fixed rep int frac -> Fixed rep int frac Source # recip :: Fixed rep int frac -> Fixed rep int frac Source # fromRational :: Rational -> Fixed rep int frac Source #
NumFixedC rep int frac => Real (Fixed rep int frac) Source # |
Instance details Defined in Clash.Sized.Fixed Methods toRational :: Fixed rep int frac -> Rational Source #
FracFixedC rep int frac => RealFrac (Fixed rep int frac) Source # |
Instance details Defined in Clash.Sized.Fixed Methods properFraction :: Integral b => Fixed rep int frac -> (b, Fixed rep int frac) Source # truncate :: Integral b => Fixed rep int frac -> b Source # round :: Integral b => Fixed rep int frac -> b Source # ceiling :: Integral b => Fixed rep int frac -> b Source # floor :: Integral b => Fixed rep int frac -> b Source #
(size ~ (int + frac), KnownNat frac, Integral (rep size)) => Show (Fixed rep int frac) Source # |
Instance details Defined in Clash.Sized.Fixed Methods showsPrec :: Int -> Fixed rep int frac -> ShowS Source # show :: Fixed rep int frac -> String Source # showList :: [Fixed rep int frac] -> ShowS Source #
Eq (rep (int + frac)) => Eq (Fixed rep int frac) Source # |
Instance details Defined in Clash.Sized.Fixed Methods (==) :: Fixed rep int frac -> Fixed rep int frac -> Bool Source # (/=) :: Fixed rep int frac -> Fixed rep int frac -> Bool Source #
Ord (rep (int + frac)) => Ord (Fixed rep int frac) Source # |

Instance details

Defined in Clash.Sized.Fixed

Methods

compare :: Fixed rep int frac -> Fixed rep int frac -> Ordering Source #

(<) :: Fixed rep int frac -> Fixed rep int frac -> Bool Source #

(<=) :: Fixed rep int frac -> Fixed rep int frac -> Bool Source #

(>) :: Fixed rep int frac -> Fixed rep int frac -> Bool Source #

(>=) :: Fixed rep int frac -> Fixed rep int frac -> Bool Source #

max :: Fixed rep int frac -> Fixed rep int frac -> Fixed rep int frac Source #

min :: Fixed rep int frac -> Fixed rep int frac -> Fixed rep int frac Source #

ENumFixedC rep int1 frac1 int2 frac2 => ExtendingNum (Fixed rep int1 frac1) (Fixed rep int2 frac2) Source #

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

- ``ENumFixedC` rep frac1 frac2 size1 size2` for: `Fixed`
- ``ENumSFixedC` int1 frac1 int2 frac2` for: `SFixed`
- ``ENumUFixedC` int1 frac1 int2 frac2` for: `UFixed`

Instance details

Defined in Clash.Sized.Fixed

Associated Types

type AResult (Fixed rep int1 frac1) (Fixed rep int2 frac2) |
Instance details Defined in Clash.Sized.Fixed 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) |
Instance details Defined in Clash.Sized.Fixed type MResult (Fixed rep int1 frac1) (Fixed rep int2 frac2) = Fixed rep (int1 + int2) (frac1 + frac2)

Methods

add :: Fixed rep int1 frac1 -> Fixed rep int2 frac2 -> AResult (Fixed rep int1 frac1) (Fixed rep int2 frac2) Source #

sub :: Fixed rep int1 frac1 -> Fixed rep int2 frac2 -> AResult (Fixed rep int1 frac1) (Fixed rep int2 frac2) Source #

mul :: Fixed rep int1 frac1 -> Fixed rep int2 frac2 -> MResult (Fixed rep int1 frac1) (Fixed rep int2 frac2) Source #

type Unbundled dom d (Fixed rep int frac) Source # |
Instance details Defined in Clash.Signal.Delayed.Bundle type Unbundled dom d (Fixed rep int frac) = DSignal dom d (Fixed rep int frac)
type TryDomain t (Fixed a n m) Source # |
Instance details Defined in Clash.Class.HasDomain.HasSingleDomain type TryDomain t (Fixed a n m) = TryDomain t (a (n + m))
type Unbundled dom (Fixed rep int frac) Source # |
Instance details Defined in Clash.Signal.Bundle type Unbundled dom (Fixed rep int frac) = Signal dom (Fixed rep int frac)
type BitSize (Fixed rep int frac) Source # |
Instance details Defined in Clash.Sized.Fixed type BitSize (Fixed rep int frac) = BitSize (rep (int + frac))
type AResult (Fixed rep int1 frac1) (Fixed rep int2 frac2) Source # |
Instance details Defined in Clash.Sized.Fixed 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) Source # |
Instance details Defined in Clash.Sized.Fixed type MResult (Fixed rep int1 frac1) (Fixed rep int2 frac2) = Fixed rep (int1 + int2) (frac1 + frac2)

resizeF :: forall (rep :: Nat -> Type) (int1 :: Natural) (frac1 :: Natural) (int2 :: Natural) (frac2 :: Natural). ResizeFC rep int1 frac1 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:

- ``ResizeFC` rep int1 frac1 int2 frac2` for: ``Fixed` rep int1 frac1 -> `Fixed` rep int2 frac2`
- ``ResizeSFC` int1 frac1 int2 frac2` for: ``SFixed` int1 frac1 -> `SFixed` int2 frac2`
- ``ResizeUFC` rep int1 frac1 int2 frac2` for: ``UFixed` int1 frac1 -> `UFixed` int2 frac2`

fracShift :: forall (frac :: Nat) (rep :: Nat -> Type) (int :: Nat). 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 a "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 `mul` y) `add` 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 `mul` y) `add` s

## Constraint synonyms for `SFixed`

type NumSFixedC (int :: Natural) (frac :: Natural) = (KnownNat ((int + int) + (frac + frac)), KnownNat (frac + frac), KnownNat (int + int), KnownNat (int + frac), KnownNat frac, KnownNat int) Source #

Constraint for the `Num` instance of `SFixed`

type ENumSFixedC (int1 :: Nat) (frac1 :: Nat) (int2 :: Natural) (frac2 :: Natural) = (KnownNat (int2 + frac2), KnownNat ((1 + Max int1 int2) + Max frac1 frac2), KnownNat (Max frac1 frac2), KnownNat (1 + Max int1 int2), KnownNat (int1 + frac1), KnownNat frac2, KnownNat int2, KnownNat frac1, KnownNat int1) Source #

Constraint for the `ExtendingNum` instance of `SFixed`

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

Constraint for the `Fractional` instance of `SFixed`

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

Constraint for the `resizeF` function, specialized for `SFixed`

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

Constraint for the `divide` function, specialized for `SFixed`

## Constraint synonyms for `UFixed`

type NumUFixedC (int :: Natural) (frac :: Natural) = NumSFixedC int frac Source #

Constraint for the `Num` instance of `UFixed`

type ENumUFixedC (int1 :: Nat) (frac1 :: Nat) (int2 :: Natural) (frac2 :: Natural) = ENumSFixedC int1 frac1 int2 frac2 Source #

Constraint for the `ExtendingNum` instance of `UFixed`

type FracUFixedC (int :: Natural) (frac :: Natural) = FracSFixedC int frac Source #

Constraint for the `Fractional` instance of `UFixed`

type ResizeUFC (int1 :: Nat) (frac1 :: Nat) (int2 :: Nat) (frac2 :: Nat) = ResizeSFC int1 frac1 int2 frac2 Source #

Constraint for the `resizeF` function, specialized for `UFixed`

type DivideUC (int1 :: Natural) (frac1 :: Natural) (int2 :: Natural) (frac2 :: Natural) = DivideSC int1 frac1 int2 frac2 Source #

Constraint for the `divide` function, specialized for `UFixed`

## Constraint synonyms for `Fixed` wrapper

type NumFixedC (rep :: Natural -> Type) (int :: Natural) (frac :: Natural) = (SaturatingNum (rep (int + frac)), ExtendingNum (rep (int + frac)) (rep (int + frac)), MResult (rep (int + frac)) (rep (int + frac)) ~ rep ((int + int) + (frac + frac)), BitSize (rep ((int + int) + (frac + frac))) ~ (int + ((int + frac) + frac)), BitPack (rep ((int + int) + (frac + frac))), Bits (rep ((int + int) + (frac + frac))), BitPack (rep (int + frac)), Bits (rep (int + frac)), Integral (rep (int + frac)), Resize rep, Typeable rep, KnownNat int, KnownNat frac) Source #

Constraint for the `Num` instance of `Fixed`

type ENumFixedC (rep :: Natural -> Type) (int1 :: Nat) (frac1 :: Nat) (int2 :: Nat) (frac2 :: Nat) = (Bounded (rep ((1 + Max int1 int2) + Max frac1 frac2)), Num (rep ((1 + Max int1 int2) + Max frac1 frac2)), Bits (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)), KnownNat int1, KnownNat int2, KnownNat frac1, KnownNat frac2, Resize rep) Source #

Constraint for the `ExtendingNum` instance of `Fixed`

type FracFixedC (rep :: Natural -> Type) (int :: Natural) (frac :: Natural) = (NumFixedC rep int frac, DivideC rep int frac int frac) Source #

Constraint for the `Fractional` instance of `Fixed`

type ResizeFC (rep :: Nat -> Type) (int1 :: Natural) (frac1 :: Natural) (int2 :: Natural) (frac2 :: Natural) = (Resize rep, Ord (rep (int1 + frac1)), Num (rep (int1 + frac1)), Bits (rep (int1 + frac1)), Bits (rep (int2 + frac2)), Bounded (rep (int2 + frac2)), KnownNat int1, KnownNat frac1, KnownNat int2, KnownNat frac2) Source #

Constraint for the `resizeF` function

type DivideC (rep :: Nat -> Type) (int1 :: Natural) (frac1 :: Natural) (int2 :: Natural) (frac2 :: Natural) = (Resize rep, Integral (rep (((int1 + frac2) + 1) + (int2 + frac1))), Bits (rep (((int1 + frac2) + 1) + (int2 + frac1))), KnownNat int1, KnownNat frac1, KnownNat int2, KnownNat frac2) Source #

Constraint for the `divide` function

# Proxy

asRepProxy :: forall (rep :: Nat -> Type) (int :: Nat) (frac :: Nat). Fixed rep int frac -> Proxy rep Source #

`Fixed` as a `Proxy` for it's representation type `rep`

asIntProxy :: forall (rep :: Nat -> Type) (int :: Nat) (frac :: Nat). Fixed rep int frac -> Proxy int Source #

`Fixed` as a `Proxy` for the number of integer bits `int`