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

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

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
>>> 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) `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, 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

Run-time Double conversion (not synthesisable)

fLitR :: forall rep int frac size. (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 functions is not synthesisable

Creating data-files

An example usage of this function is for example to convert a data file containing Doubles to a data file with ASCI-encoded binary numbers to be used by a synthesisable function like asyncRomFile. For example, given 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 System.Environment
import qualified Data.List as L

createRomFile :: KnownNat n => (Double -> BitVector n)
              -> 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
      bvs = L.map (filter (/= '_') . show . convert) ds
  writeFile fileW (unlines bvs)

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

main :: IO ()
main = do
  [fileR,fileW] <- getArgs
  createRomFile (pack . 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 Doubles to a Data.bin file which will containing the desired ASCI-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 qualified Data.List        as L
import Language.Haskell.TH        (ExpQ, litE, stringL)
import Language.Haskell.TH.Syntax (qRunIO)

createRomFile :: KnownNat n => (Double -> BitVector n)
              -> 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
      bvs = L.map (filter (/= '_') . show . convert) ds
  writeFile fileW (unlines bvs)

romDataFromFile :: KnownNat n => (Double -> BitVector n) -> String -> ExpQ
romDataFromFile convert fileR = do
  let fileW = fileR L.++ ".bin"
  bvF <- 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

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

romF' :: Unsigned 3 -> Unsigned 3 -> SFixed 8 8
romF' rowAddr colAddr = unpack $
  asyncRomFile d8
               $(romDataFromFile (pack . toSFixed8_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 -> *) (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.

Constructors

Fixed 

Fields

Instances
Bounded (rep (int + frac)) => Bounded (Fixed rep int frac) Source # 
Instance details

Methods

minBound :: Fixed rep int frac #

maxBound :: Fixed rep int frac #

Enum (rep (int + frac)) => Enum (Fixed rep int frac) Source # 
Instance details

Methods

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

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

toEnum :: Int -> Fixed rep int frac #

fromEnum :: Fixed rep int frac -> Int #

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

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

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

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

Eq (rep (int + frac)) => Eq (Fixed rep int frac) Source # 
Instance details

Methods

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

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

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:

Instance details

Methods

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

recip :: Fixed rep int frac -> Fixed rep int frac #

fromRational :: Rational -> Fixed rep int frac #

(Typeable rep, Typeable int, Typeable frac, Data (rep (int + frac))) => Data (Fixed rep int frac) Source # 
Instance details

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) #

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

toConstr :: Fixed rep int frac -> Constr #

dataTypeOf :: Fixed rep int frac -> DataType #

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

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

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

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

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

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

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

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

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

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

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:

Instance details

Methods

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

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

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

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

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

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

fromInteger :: Integer -> Fixed rep int frac #

Ord (rep (int + frac)) => Ord (Fixed rep int frac) Source # 
Instance details

Methods

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

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

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

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

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

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

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

(size ~ (int + frac), KnownNat frac, Bounded (rep size), Integral (rep size)) => Read (Fixed rep int frac) Source #

None of the Read class' methods are synthesisable.

Instance details

Methods

readsPrec :: Int -> ReadS (Fixed rep int frac) #

readList :: ReadS [Fixed rep int frac] #

readPrec :: ReadPrec (Fixed rep int frac) #

readListPrec :: ReadPrec [Fixed rep int frac] #

(NumFixedC rep int frac, Integral (rep (int + frac))) => Real (Fixed rep int frac) Source # 
Instance details

Methods

toRational :: Fixed rep int frac -> Rational #

(size ~ (int + frac), KnownNat frac, Integral (rep size)) => Show (Fixed rep int frac) Source # 
Instance details

Methods

showsPrec :: Int -> Fixed rep int frac -> ShowS #

show :: Fixed rep int frac -> String #

showList :: [Fixed rep int frac] -> ShowS #

(Lift (rep (int + frac)), KnownNat frac, KnownNat int, Typeable rep) => Lift (Fixed rep int frac) Source # 
Instance details

Methods

lift :: Fixed rep int frac -> Q Exp #

Arbitrary (rep (int + frac)) => Arbitrary (Fixed rep int frac) Source # 
Instance details

Methods

arbitrary :: Gen (Fixed rep int frac) #

shrink :: Fixed rep int frac -> [Fixed rep int frac] #

CoArbitrary (rep (int + frac)) => CoArbitrary (Fixed rep int frac) Source # 
Instance details

Methods

coarbitrary :: Fixed rep int frac -> Gen b -> Gen b #

Bits (rep (int + frac)) => Bits (Fixed rep int frac) Source #

Instance functions do not saturate. Meaning that "`shiftL' 1 == satMult SatWrap 2'""

Instance details

Methods

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

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

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

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

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

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

zeroBits :: Fixed rep int frac #

bit :: Int -> Fixed rep int frac #

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

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

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

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

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

bitSize :: Fixed rep int frac -> Int #

isSigned :: Fixed rep int frac -> Bool #

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

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

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

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

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

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

popCount :: Fixed rep int frac -> Int #

FiniteBits (rep (int + frac)) => FiniteBits (Fixed rep int frac) Source # 
Instance details

Methods

finiteBitSize :: Fixed rep int frac -> Int #

countLeadingZeros :: Fixed rep int frac -> Int #

countTrailingZeros :: Fixed rep int frac -> Int #

Default (rep (int + frac)) => Default (Fixed rep int frac) Source # 
Instance details

Methods

def :: Fixed rep int frac #

NFData (rep (int + frac)) => NFData (Fixed rep int frac) Source # 
Instance details

Methods

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

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

Methods

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

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

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

(size ~ (int + frac), KnownNat frac, Integral (rep size)) => ShowX (Fixed rep int frac) Source # 
Instance details

Methods

showsPrecX :: Int -> Fixed rep int frac -> ShowS Source #

showX :: Fixed rep int frac -> String Source #

showListX :: [Fixed rep int frac] -> ShowS Source #

BitPack (rep (int + frac)) => BitPack (Fixed rep int frac) Source # 
Instance details

Associated Types

type BitSize (Fixed rep int frac) :: Nat Source #

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 #

Bundle (Fixed rep int frac) Source # 
Instance details

Associated Types

type Unbundled domain (Fixed rep int frac) = (res :: *) Source #

Methods

bundle :: Unbundled domain (Fixed rep int frac) -> Signal domain (Fixed rep int frac) Source #

unbundle :: Signal domain (Fixed rep int frac) -> Unbundled domain (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:

Instance details

Associated Types

type AResult (Fixed rep int1 frac1) (Fixed rep int2 frac2) :: * Source #

type MResult (Fixed rep int1 frac1) (Fixed rep int2 frac2) :: * Source #

Methods

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

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

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

type Unbundled domain (Fixed rep int frac) Source # 
Instance details
type Unbundled domain (Fixed rep int frac) = Signal domain (Fixed rep int frac)
type BitSize (Fixed rep int frac) Source # 
Instance details
type BitSize (Fixed rep int frac) = BitSize (rep (int + frac))
type AResult (Fixed rep int1 frac1) (Fixed rep int2 frac2) Source # 
Instance details
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
type MResult (Fixed rep int1 frac1) (Fixed rep int2 frac2) = Fixed rep (int1 + int2) (frac1 + frac2)

resizeF :: forall rep int1 frac1 int2 frac2. 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:

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 ((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 frac1 int2 frac2 = (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 frac = (NumSFixedC int frac, KnownNat (((int + frac) + 1) + (int + frac))) Source #

Constraint for the Fractional instance of SFixed

type ResizeSFC int1 frac1 int2 frac2 = (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 frac1 int2 frac2 = (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 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)), 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))), KnownNat (BitSize (rep (int + frac))), BitPack (rep (int + frac)), Enum (rep (int + frac)), Bits (rep (int + frac)), Resize rep, KnownNat int, KnownNat frac) Source #

Constraint for the Num instance of Fixed

type ENumFixedC rep int1 frac1 int2 frac2 = (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 int frac = (NumFixedC rep int frac, DivideC rep int frac int frac, Integral (rep (int + frac)), KnownNat int, KnownNat 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)), Bounded (rep (int2 + frac2)), KnownNat int1, KnownNat frac1, KnownNat int2, KnownNat 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 int1, KnownNat frac1, KnownNat int2, KnownNat frac2) Source #

Constraint for the divide function

Proxy

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

Fixed as a Proxy for it's representation type rep

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

Fixed as a Proxy for the number of integer bits int