    {-|
    Copyright  :  (C) 2013-2016, University of Twente,
                      2016-2017, Myrtle Software Ltd,
                      2021-2025, QBayLogic B.V.,
                      2022,      Google Inc.
    License    :  BSD2 (see the file LICENSE)
    Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>
    -}

    {-# LANGUAGE CPP #-}
    {-# LANGUAGE FlexibleContexts #-}
    {-# LANGUAGE TemplateHaskell #-}
    {-# LANGUAGE TypeFamilies #-}
    {-# LANGUAGE UndecidableInstances #-}

    {-# LANGUAGE Trustworthy #-}

    {-# OPTIONS_GHC -fplugin=GHC.TypeLits.Extra.Solver #-}
    {-# OPTIONS_GHC -fplugin=GHC.TypeLits.Normalise #-}
    {-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-}
    {-# OPTIONS_HADDOCK show-extensions #-}

    #include "MachDeps.h"

    module Clash.Class.BitPack.Internal where

    import Prelude                        hiding (map)

    import Data.Binary.IEEE754            (doubleToWord, floatToWord, wordToDouble,
                                           wordToFloat)

    import Data.Complex                   (Complex)
    import Data.Functor.Compose           (Compose)
    import Data.Functor.Const             (Const)
    import Data.Functor.Identity          (Identity)
    import Data.Functor.Product           (Product)
    import Data.Functor.Sum               (Sum)
    import Data.Char                      (chr, ord)
    import Data.Int
    import Data.Ord                       (Down)
    import Data.Word
    import Foreign.C.Types                (CUShort)
    import GHC.Generics
    import GHC.TypeLits                   (KnownNat, Nat, type (+), type (-))
    import GHC.TypeLits.Extra             (CLog, Max)
    import Numeric.Half                   (Half (..))

    import Clash.Annotations.Primitive    (hasBlackBox)
    import Clash.Class.BitPack.Internal.TH (deriveBitPackTuples)
    import Clash.Class.Resize             (zeroExtend, resize)
    import Clash.Promoted.Nat             (SNat(..), snatToNum)
    import Clash.Sized.Internal.BitVector
      (pack#, split#, checkUnpackUndef, undefined#, unpack#, unsafeToNatural, isLike#,
       BitVector, Bit, (++#), xToBV)

    {- $setup
    >>> :m -Prelude
    >>> :set -XDataKinds
    >>> import Clash.Prelude
    -}

    -- | Convert data to/from a 'BitVector'. This allows functions to be defined
    -- on the underlying representation of data, while exposing a nicer API using
    -- 'pack' / 'unpack' at the boundaries. For example:
    --
    -- @
    --     f :: forall a b. (BitPack a, BitPack b) => a -> b
    --     f = unpack . go . pack
    --      where
    --       go :: BitVector (BitSize a) -> BitVector (BitSize b)
    --       go = _ -- A function on the underlying bit vector
    -- @
    --
    -- A type should only implement this class if it has a statically known size,
    -- as otherwise it is not possible to determine how many bits are needed to
    -- represent values. This means that types such as @[a]@ cannot have @BitPack@
    -- instances, as even if @a@ has a statically known size, the length of the
    -- list cannot be known in advance.
    --
    -- It is not possible to give data a custom bit representation by providing a
    -- @BitPack@ instance. A @BitPack@ instance allows no creativity and should
    -- always accurately reflect the bit representation of the data in HDL. You
    -- should always @derive ('Generic', BitPack)@ unless you use a custom data
    -- representation, in which case you should use
    -- 'Clash.Annotations.BitRepresentation.Deriving.deriveBitPack'. Custom
    -- encodings can be created with "Clash.Annotations.BitRepresentation" and
    -- "Clash.Annotations.BitRepresentation.Deriving".
    --
    -- If the @BitPack@ instance does not accurately match the bit representation of
    -- the data in HDL, Clash designs will exhibit incorrect behavior in various
    -- places.
    --
    -- Clash provides some generic functions on packable types in the prelude, such
    -- as indexing into packable stuctures (see "Clash.Class.BitPack.BitIndex") and
    -- bitwise reduction of packable data (see "Clash.Class.BitPack.BitReduction").
    --
    class KnownNat (BitSize a) => BitPack a where
      -- | Number of 'Clash.Sized.BitVector.Bit's needed to represents elements
      -- of type @a@
      --
      -- Can be derived using `GHC.Generics`:
      --
      -- > import Clash.Prelude
      -- > import GHC.Generics
      -- >
      -- > data MyProductType = MyProductType { a :: Int, b :: Bool }
      -- >   deriving (Generic, BitPack)
      type BitSize a :: Nat
      type BitSize a = (CLog 2 (GConstructorCount (Rep a))) + (GFieldSize (Rep a))
      -- | Convert element of type @a@ to a 'BitVector'
      --
      -- >>> pack (-5 :: Signed 6)
      -- 0b11_1011
      pack   :: a -> BitVector (BitSize a)
      default pack
        :: ( Generic a
           , GBitPack (Rep a)
           , KnownNat (BitSize a)
           , KnownNat constrSize
           , KnownNat fieldSize
           , constrSize ~ CLog 2 (GConstructorCount (Rep a))
           , fieldSize ~ GFieldSize (Rep a)
           , (constrSize + fieldSize) ~ BitSize a
           )
        => a -> BitVector (BitSize a)
      pack = (a -> BitVector (BitSize a)) -> a -> BitVector (BitSize a)
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith a -> BitVector (constrSize + GFieldSize (Rep a))
    a -> BitVector (BitSize a)
    forall {a} {n :: Natural}.
    (GBitPack (Rep a), Generic a, KnownNat n,
     KnownNat (GFieldSize (Rep a))) =>
    a -> BitVector (n + GFieldSize (Rep a))
    go
       where
        go :: a -> BitVector (n + GFieldSize (Rep a))
    go a
    a = BitVector 64 -> BitVector n
    forall (a :: Natural) (b :: Natural).
    (KnownNat a, KnownNat b) =>
    BitVector a -> BitVector b
    forall (f :: Natural -> Type) (a :: Natural) (b :: Natural).
    (Resize f, KnownNat a, KnownNat b) =>
    f a -> f b
    resize (Int -> BitVector (BitSize Int)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack Int
    sc) BitVector n
    -> BitVector (GFieldSize (Rep a))
    -> BitVector (n + GFieldSize (Rep a))
    forall (m :: Natural) (n :: Natural).
    KnownNat m =>
    BitVector n -> BitVector m -> BitVector (n + m)
    ++# BitVector (GFieldSize (Rep a))
    packedFields
         where
          (Int
    sc, BitVector (GFieldSize (Rep a))
    packedFields) = Int -> Rep a (ZonkAny 0) -> (Int, BitVector (GFieldSize (Rep a)))
    forall a. Int -> Rep a a -> (Int, BitVector (GFieldSize (Rep a)))
    forall (f :: Type -> Type) a.
    GBitPack f =>
    Int -> f a -> (Int, BitVector (GFieldSize f))
    gPackFields Int
    0 (a -> Rep a (ZonkAny 0)
    forall x. a -> Rep a x
    forall a x. Generic a => a -> Rep a x
    from a
    a)

      -- | Convert a 'BitVector' to an element of type @a@
      --
      -- >>> pack (-5 :: Signed 6)
      -- 0b11_1011
      -- >>> let x = pack (-5 :: Signed 6)
      -- >>> unpack x :: Unsigned 6
      -- 59
      -- >>> pack (59 :: Unsigned 6)
      -- 0b11_1011
      unpack :: BitVector (BitSize a) -> a
      default unpack
        :: ( Generic a
           , GBitPack (Rep a)
           , KnownNat constrSize
           , KnownNat fieldSize
           , constrSize ~ CLog 2 (GConstructorCount (Rep a))
           , fieldSize ~ GFieldSize (Rep a)
           , (constrSize + fieldSize) ~ BitSize a
           )
        => BitVector (BitSize a) -> a
      unpack BitVector (BitSize a)
    b =
        Rep a (ZonkAny 1) -> a
    forall a x. Generic a => Rep a x -> a
    forall x. Rep a x -> a
    to (Int -> Int -> BitVector (GFieldSize (Rep a)) -> Rep a (ZonkAny 1)
    forall a. Int -> Int -> BitVector (GFieldSize (Rep a)) -> Rep a a
    forall (f :: Type -> Type) a.
    GBitPack f =>
    Int -> Int -> BitVector (GFieldSize f) -> f a
    gUnpack Int
    sc Int
    0 BitVector fieldSize
    BitVector (GFieldSize (Rep a))
    bFields)
       where
        ((BitVector 64 -> Int) -> BitVector 64 -> Int
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 64 -> Int
    BitVector (BitSize Int) -> Int
    forall a. BitPack a => BitVector (BitSize a) -> a
    unpack (BitVector 64 -> Int)
    -> (BitVector constrSize -> BitVector 64)
    -> BitVector constrSize
    -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . BitVector constrSize -> BitVector 64
    forall (a :: Natural) (b :: Natural).
    (KnownNat a, KnownNat b) =>
    BitVector a -> BitVector b
    forall (f :: Natural -> Type) (a :: Natural) (b :: Natural).
    (Resize f, KnownNat a, KnownNat b) =>
    f a -> f b
    resize -> Int
    sc, BitVector fieldSize
    bFields) = BitVector (constrSize + fieldSize)
    -> (BitVector constrSize, BitVector fieldSize)
    forall (n :: Natural) (m :: Natural).
    KnownNat n =>
    BitVector (m + n) -> (BitVector m, BitVector n)
    split# BitVector (constrSize + fieldSize)
    BitVector (BitSize a)
    b

    packXWith
      :: KnownNat n
      => (a -> BitVector n)
      -> a
      -> BitVector n
    packXWith :: forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith a -> BitVector n
    f = BitVector n -> BitVector n
    forall (n :: Natural). KnownNat n => BitVector n -> BitVector n
    xToBV (BitVector n -> BitVector n)
    -> (a -> BitVector n) -> a -> BitVector n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> BitVector n
    f
    {-# INLINE packXWith #-}

    -- | Pack both arguments to a 'BitVector' and use
    -- 'Clash.Sized.Internal.BitVector.isLike#' to compare them. This is a more
    -- lentiant comparison than '(==)', behaving more like (but not necessarily
    -- exactly the same as) @std_match@ in VHDL or @casez@ in Verilog.
    --
    -- Unlike '(==)', isLike is not symmetric. The reason for this is that a
    -- defined bit is said to be like an undefined bit, but not vice-versa:
    --
    -- >>> isLike (12 :: Signed 8) undefined
    -- True
    -- >>> isLike undefined (12 :: Signed 8)
    -- False
    --
    -- However, it is still trivially reflexive and transitive:
    --
    -- >>> :set -XTemplateHaskell
    -- >>> let x1 = $(bLit "0010")
    -- >>> let x2 = $(bLit "0.10")
    -- >>> let x3 = $(bLit "0.1.")
    -- >>> isLike x1 x1
    -- True
    -- >>> isLike x1 x2
    -- True
    -- >>> isLike x2 x3
    -- True
    -- >>> isLike x1 x3
    -- True
    --
    -- __NB__: Not synthesizable
    --
    isLike
      :: (BitPack a)
      => a
      -> a
      -> Bool
    isLike :: forall a. BitPack a => a -> a -> Bool
    isLike a
    x a
    y =
      BitVector (BitSize a) -> BitVector (BitSize a) -> Bool
    forall (n :: Natural).
    KnownNat n =>
    BitVector n -> BitVector n -> Bool
    isLike# (a -> BitVector (BitSize a)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack a
    x) (a -> BitVector (BitSize a)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack a
    y)

    {-# INLINE[1] bitCoerce #-}
    -- | Coerce a value from one type to another through its bit representation.
    --
    -- >>> pack (-5 :: Signed 6)
    -- 0b11_1011
    -- >>> bitCoerce (-5 :: Signed 6) :: Unsigned 6
    -- 59
    -- >>> pack (59 :: Unsigned 6)
    -- 0b11_1011
    bitCoerce
      :: (BitPack a, BitPack b, BitSize a ~ BitSize b)
      => a
      -> b
    bitCoerce :: forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
    bitCoerce = BitVector (BitSize b) -> b
    forall a. BitPack a => BitVector (BitSize a) -> a
    unpack (BitVector (BitSize b) -> b)
    -> (a -> BitVector (BitSize b)) -> a -> b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> BitVector (BitSize a)
    a -> BitVector (BitSize b)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack

    -- | Map a value by first coercing to another type through its bit representation.
    --
    -- >>> pack (-5 :: Signed 32)
    -- 0b1111_1111_1111_1111_1111_1111_1111_1011
    -- >>> bitCoerceMap @(Vec 4 (BitVector 8)) (replace 1 0) (-5 :: Signed 32)
    -- -16711685
    -- >>> pack (-16711685 :: Signed 32)
    -- 0b1111_1111_0000_0000_1111_1111_1111_1011
    bitCoerceMap
      :: forall a b . (BitPack a, BitPack b, BitSize a ~ BitSize b)
      => (a -> a)
      -> b
      -> b
    bitCoerceMap :: forall a b.
    (BitPack a, BitPack b, BitSize a ~ BitSize b) =>
    (a -> a) -> b -> b
    bitCoerceMap a -> a
    f = a -> b
    forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
    bitCoerce (a -> b) -> (b -> a) -> b -> b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> a
    f (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . b -> a
    forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
    bitCoerce

    instance BitPack Bool where
      type BitSize Bool = 1
      pack :: Bool -> BitVector (BitSize Bool)
    pack   = let go :: Bool -> a
    go Bool
    b = if Bool
    b then a
    1 else a
    0 in (Bool -> BitVector 1) -> Bool -> BitVector 1
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Bool -> BitVector 1
    forall {a}. Num a => Bool -> a
    go
      unpack :: BitVector (BitSize Bool) -> Bool
    unpack = (BitVector (BitSize Bool) -> Bool)
    -> BitVector (BitSize Bool) -> Bool
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef ((BitVector (BitSize Bool) -> Bool)
     -> BitVector (BitSize Bool) -> Bool)
    -> (BitVector (BitSize Bool) -> Bool)
    -> BitVector (BitSize Bool)
    -> Bool
    forall a b. (a -> b) -> a -> b
    $ \BitVector (BitSize Bool)
    bv -> if BitVector 1
    BitVector (BitSize Bool)
    bv BitVector 1 -> BitVector 1 -> Bool
    forall a. Eq a => a -> a -> Bool
    == BitVector 1
    1 then Bool
    True else Bool
    False

    instance KnownNat n => BitPack (BitVector n) where
      type BitSize (BitVector n) = n
      pack :: BitVector n -> BitVector (BitSize (BitVector n))
    pack     = (BitVector n -> BitVector n) -> BitVector n -> BitVector n
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith BitVector n -> BitVector n
    forall a. a -> a
    id
      unpack :: BitVector (BitSize (BitVector n)) -> BitVector n
    unpack BitVector (BitSize (BitVector n))
    v = BitVector n
    BitVector (BitSize (BitVector n))
    v

    instance BitPack Bit where
      type BitSize Bit = 1
      pack :: Bit -> BitVector (BitSize Bit)
    pack   = (Bit -> BitVector 1) -> Bit -> BitVector 1
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Bit -> BitVector 1
    pack#
      unpack :: BitVector (BitSize Bit) -> Bit
    unpack = BitVector 1 -> Bit
    BitVector (BitSize Bit) -> Bit
    unpack#

    instance BitPack Int where
      type BitSize Int = WORD_SIZE_IN_BITS
      pack :: Int -> BitVector (BitSize Int)
    pack   = (Int -> BitVector 64) -> Int -> BitVector 64
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Int -> BitVector 64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
      unpack :: BitVector (BitSize Int) -> Int
    unpack = (BitVector 64 -> Int) -> BitVector 64 -> Int
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral

    instance BitPack Int8 where
      type BitSize Int8 = 8
      pack :: Int8 -> BitVector (BitSize Int8)
    pack   = (Int8 -> BitVector 8) -> Int8 -> BitVector 8
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Int8 -> BitVector 8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
      unpack :: BitVector (BitSize Int8) -> Int8
    unpack = (BitVector 8 -> Int8) -> BitVector 8 -> Int8
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 8 -> Int8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral

    instance BitPack Int16 where
      type BitSize Int16 = 16
      pack :: Int16 -> BitVector (BitSize Int16)
    pack   = (Int16 -> BitVector 16) -> Int16 -> BitVector 16
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Int16 -> BitVector 16
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
      unpack :: BitVector (BitSize Int16) -> Int16
    unpack = (BitVector 16 -> Int16) -> BitVector 16 -> Int16
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 16 -> Int16
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral

    instance BitPack Int32 where
      type BitSize Int32 = 32
      pack :: Int32 -> BitVector (BitSize Int32)
    pack   = (Int32 -> BitVector 32) -> Int32 -> BitVector 32
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Int32 -> BitVector 32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
      unpack :: BitVector (BitSize Int32) -> Int32
    unpack = (BitVector 32 -> Int32) -> BitVector 32 -> Int32
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 32 -> Int32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral

    instance BitPack Int64 where
      type BitSize Int64 = 64
      pack :: Int64 -> BitVector (BitSize Int64)
    pack   = (Int64 -> BitVector 64) -> Int64 -> BitVector 64
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Int64 -> BitVector 64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
      unpack :: BitVector (BitSize Int64) -> Int64
    unpack = (BitVector 64 -> Int64) -> BitVector 64 -> Int64
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 64 -> Int64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral

    instance BitPack Word where
      type BitSize Word = WORD_SIZE_IN_BITS
      pack :: Word -> BitVector (BitSize Word)
    pack   = (Word -> BitVector 64) -> Word -> BitVector 64
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Word -> BitVector 64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
      unpack :: BitVector (BitSize Word) -> Word
    unpack = (BitVector 64 -> Word) -> BitVector 64 -> Word
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 64 -> Word
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral

    instance BitPack Word8 where
      type BitSize Word8 = 8
      pack :: Word8 -> BitVector (BitSize Word8)
    pack   = (Word8 -> BitVector 8) -> Word8 -> BitVector 8
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Word8 -> BitVector 8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
      unpack :: BitVector (BitSize Word8) -> Word8
    unpack = (BitVector 8 -> Word8) -> BitVector 8 -> Word8
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 8 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral

    instance BitPack Word16 where
      type BitSize Word16 = 16
      pack :: Word16 -> BitVector (BitSize Word16)
    pack   = (Word16 -> BitVector 16) -> Word16 -> BitVector 16
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Word16 -> BitVector 16
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
      unpack :: BitVector (BitSize Word16) -> Word16
    unpack = (BitVector 16 -> Word16) -> BitVector 16 -> Word16
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 16 -> Word16
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral

    instance BitPack Word32 where
      type BitSize Word32 = 32
      pack :: Word32 -> BitVector (BitSize Word32)
    pack   = (Word32 -> BitVector 32) -> Word32 -> BitVector 32
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Word32 -> BitVector 32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
      unpack :: BitVector (BitSize Word32) -> Word32
    unpack = (BitVector 32 -> Word32) -> BitVector 32 -> Word32
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 32 -> Word32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral

    instance BitPack Word64 where
      type BitSize Word64 = 64
      pack :: Word64 -> BitVector (BitSize Word64)
    pack   = (Word64 -> BitVector 64) -> Word64 -> BitVector 64
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Word64 -> BitVector 64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
      unpack :: BitVector (BitSize Word64) -> Word64
    unpack = (BitVector 64 -> Word64) -> BitVector 64 -> Word64
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 64 -> Word64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral

    instance BitPack Float where
      type BitSize Float = 32
      pack :: Float -> BitVector (BitSize Float)
    pack   = (Float -> BitVector 32) -> Float -> BitVector 32
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Float -> BitVector 32
    packFloat#
      unpack :: BitVector (BitSize Float) -> Float
    unpack = (BitVector 32 -> Float) -> BitVector 32 -> Float
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 32 -> Float
    unpackFloat#

    packFloat# :: Float -> BitVector 32
    packFloat# :: Float -> BitVector 32
    packFloat# = Word32 -> BitVector 32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word32 -> BitVector 32)
    -> (Float -> Word32) -> Float -> BitVector 32
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Float -> Word32
    floatToWord
    -- See: https://github.com/clash-lang/clash-compiler/pull/2511
    {-# CLASH_OPAQUE packFloat# #-}
    {-# ANN packFloat# hasBlackBox #-}

    unpackFloat# :: BitVector 32 -> Float
    unpackFloat# :: BitVector 32 -> Float
    unpackFloat# (BitVector 32 -> Natural
    forall (n :: Natural). BitVector n -> Natural
    unsafeToNatural -> Natural
    w) = Word32 -> Float
    wordToFloat (Natural -> Word32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Natural
    w)
    -- See: https://github.com/clash-lang/clash-compiler/pull/2511
    {-# CLASH_OPAQUE unpackFloat# #-}
    {-# ANN unpackFloat# hasBlackBox #-}

    instance BitPack Double where
      type BitSize Double = 64
      pack :: Double -> BitVector (BitSize Double)
    pack   = (Double -> BitVector 64) -> Double -> BitVector 64
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Double -> BitVector 64
    packDouble#
      unpack :: BitVector (BitSize Double) -> Double
    unpack = (BitVector 64 -> Double) -> BitVector 64 -> Double
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 64 -> Double
    unpackDouble#

    packDouble# :: Double -> BitVector 64
    packDouble# :: Double -> BitVector 64
    packDouble# = Word64 -> BitVector 64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64 -> BitVector 64)
    -> (Double -> Word64) -> Double -> BitVector 64
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Double -> Word64
    doubleToWord
    -- See: https://github.com/clash-lang/clash-compiler/pull/2511
    {-# CLASH_OPAQUE packDouble# #-}
    {-# ANN packDouble# hasBlackBox #-}

    unpackDouble# :: BitVector 64 -> Double
    unpackDouble# :: BitVector 64 -> Double
    unpackDouble# (BitVector 64 -> Natural
    forall (n :: Natural). BitVector n -> Natural
    unsafeToNatural -> Natural
    w) = Word64 -> Double
    wordToDouble (Natural -> Word64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Natural
    w)
    -- See: https://github.com/clash-lang/clash-compiler/pull/2511
    {-# CLASH_OPAQUE unpackDouble# #-}
    {-# ANN unpackDouble# hasBlackBox #-}

    instance BitPack CUShort where
      type BitSize CUShort = 16
      pack :: CUShort -> BitVector (BitSize CUShort)
    pack   = (CUShort -> BitVector 16) -> CUShort -> BitVector 16
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith CUShort -> BitVector 16
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
      unpack :: BitVector (BitSize CUShort) -> CUShort
    unpack = (BitVector 16 -> CUShort) -> BitVector 16 -> CUShort
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 16 -> CUShort
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral

    instance BitPack Half where
      type BitSize Half = 16
      pack :: Half -> BitVector (BitSize Half)
    pack (Half CUShort
    x) = CUShort -> BitVector (BitSize CUShort)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack CUShort
    x
      unpack :: BitVector (BitSize Half) -> Half
    unpack        = (BitVector (BitSize Half) -> Half)
    -> BitVector (BitSize Half) -> Half
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef ((BitVector (BitSize Half) -> Half)
     -> BitVector (BitSize Half) -> Half)
    -> (BitVector (BitSize Half) -> Half)
    -> BitVector (BitSize Half)
    -> Half
    forall a b. (a -> b) -> a -> b
    $ \BitVector (BitSize Half)
    x -> CUShort -> Half
    Half (BitVector (BitSize CUShort) -> CUShort
    forall a. BitPack a => BitVector (BitSize a) -> a
    unpack BitVector (BitSize CUShort)
    BitVector (BitSize Half)
    x)

    instance BitPack () where
      type BitSize () = 0
      pack :: () -> BitVector (BitSize ())
    pack   ()
    _ = BitVector 0
    BitVector (BitSize ())
    forall a. Bounded a => a
    minBound
      unpack :: BitVector (BitSize ()) -> ()
    unpack BitVector (BitSize ())
    _ = ()

    instance BitPack Char where
      type BitSize Char = 21
      pack :: Char -> BitVector (BitSize Char)
    pack   = (Char -> BitVector 21) -> Char -> BitVector 21
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith Char -> BitVector 21
    packChar#
      unpack :: BitVector (BitSize Char) -> Char
    unpack = (BitVector 21 -> Char) -> BitVector 21 -> Char
    forall (n :: Natural) a.
    (KnownNat n, Typeable a) =>
    (BitVector n -> a) -> BitVector n -> a
    checkUnpackUndef BitVector 21 -> Char
    unpackChar#

    packChar# :: Char -> BitVector 21
    packChar# :: Char -> BitVector 21
    packChar# = Int -> BitVector 21
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> BitVector 21) -> (Char -> Int) -> Char -> BitVector 21
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> Int
    ord
    -- See: https://github.com/clash-lang/clash-compiler/pull/2511
    {-# CLASH_OPAQUE packChar# #-}
    {-# ANN packChar# hasBlackBox #-}

    unpackChar# :: BitVector 21 -> Char
    unpackChar# :: BitVector 21 -> Char
    unpackChar# = Int -> Char
    chr (Int -> Char) -> (BitVector 21 -> Int) -> BitVector 21 -> Char
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . BitVector 21 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
    -- See: https://github.com/clash-lang/clash-compiler/pull/2511
    {-# CLASH_OPAQUE unpackChar# #-}
    {-# ANN unpackChar# hasBlackBox #-}

    -- | __NB__: The documentation only shows instances up to /3/-tuples. By
    -- default, instances up to and including /12/-tuples will exist. If the flag
    -- @large-tuples@ is set instances up to the GHC imposed limit will exist. The
    -- GHC imposed limit is either 62 or 64 depending on the GHC version.
    instance (BitPack a, BitPack b) => BitPack (a,b) where
      type BitSize (a,b) = BitSize a + BitSize b
      pack :: (a, b) -> BitVector (BitSize (a, b))
    pack = let go :: (a, a) -> BitVector (BitSize a + BitSize a)
    go (a
    a,a
    b) = a -> BitVector (BitSize a)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack a
    a BitVector (BitSize a)
    -> BitVector (BitSize a) -> BitVector (BitSize a + BitSize a)
    forall (m :: Natural) (n :: Natural).
    KnownNat m =>
    BitVector n -> BitVector m -> BitVector (n + m)
    ++# a -> BitVector (BitSize a)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack a
    b in ((a, b) -> BitVector (BitSize a + BitSize b))
    -> (a, b) -> BitVector (BitSize a + BitSize b)
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith (a, b) -> BitVector (BitSize a + BitSize b)
    forall {a} {a}.
    (BitPack a, BitPack a) =>
    (a, a) -> BitVector (BitSize a + BitSize a)
    go
      unpack :: BitVector (BitSize (a, b)) -> (a, b)
    unpack BitVector (BitSize (a, b))
    ab  = let (BitVector (BitSize a)
    a,BitVector (BitSize b)
    b) = BitVector (BitSize a + BitSize b)
    -> (BitVector (BitSize a), BitVector (BitSize b))
    forall (n :: Natural) (m :: Natural).
    KnownNat n =>
    BitVector (m + n) -> (BitVector m, BitVector n)
    split# BitVector (BitSize a + BitSize b)
    BitVector (BitSize (a, b))
    ab in (BitVector (BitSize a) -> a
    forall a. BitPack a => BitVector (BitSize a) -> a
    unpack BitVector (BitSize a)
    a, BitVector (BitSize b) -> b
    forall a. BitPack a => BitVector (BitSize a) -> a
    unpack BitVector (BitSize b)
    b)

    class GBitPack f where
      -- | Size of fields. If multiple constructors exist, this is the maximum of
      -- the sum of each of the constructors fields.
      type GFieldSize f :: Nat

      -- | Number of constructors this type has. Indirectly indicates how many bits
      -- are needed to represent the constructor.
      type GConstructorCount f :: Nat

      -- | Pack fields of a type. Caller should pack and prepend the constructor bits.
      gPackFields
        :: Int
        -- ^ Current constructor
        -> f a
        -- ^ Data to pack
        -> (Int, BitVector (GFieldSize f))
        -- ^ (Constructor number, Packed fields)

      -- | Unpack whole type.
      gUnpack
        :: Int
        -- ^ Construct with constructor /n/
        -> Int
        -- ^ Current constructor
        -> BitVector (GFieldSize f)
        -- ^ BitVector containing fields
        -> f a
        -- ^ Unpacked result

    instance GBitPack a => GBitPack (M1 m d a) where
      type GFieldSize (M1 m d a) = GFieldSize a
      type GConstructorCount (M1 m d a) = GConstructorCount a

      gPackFields :: forall a.
    Int -> M1 m d a a -> (Int, BitVector (GFieldSize (M1 m d a)))
    gPackFields Int
    cc (M1 a a
    m1) = Int -> a a -> (Int, BitVector (GFieldSize a))
    forall a. Int -> a a -> (Int, BitVector (GFieldSize a))
    forall (f :: Type -> Type) a.
    GBitPack f =>
    Int -> f a -> (Int, BitVector (GFieldSize f))
    gPackFields Int
    cc a a
    m1
      gUnpack :: forall a.
    Int -> Int -> BitVector (GFieldSize (M1 m d a)) -> M1 m d a a
    gUnpack Int
    c Int
    cc BitVector (GFieldSize (M1 m d a))
    b = a a -> M1 m d a a
    forall k i (c :: Meta) (f :: k -> Type) (p :: k). f p -> M1 i c f p
    M1 (Int -> Int -> BitVector (GFieldSize a) -> a a
    forall a. Int -> Int -> BitVector (GFieldSize a) -> a a
    forall (f :: Type -> Type) a.
    GBitPack f =>
    Int -> Int -> BitVector (GFieldSize f) -> f a
    gUnpack Int
    c Int
    cc BitVector (GFieldSize a)
    BitVector (GFieldSize (M1 m d a))
    b)

    instance ( KnownNat (GFieldSize g)
             , KnownNat (GFieldSize f)
             , KnownNat (GConstructorCount f)
             , GBitPack f
             , GBitPack g
             ) => GBitPack (f :+: g) where
      type GFieldSize (f :+: g) = Max (GFieldSize f) (GFieldSize g)
      type GConstructorCount (f :+: g) = GConstructorCount f + GConstructorCount g

      gPackFields :: forall a.
    Int -> (:+:) f g a -> (Int, BitVector (GFieldSize (f :+: g)))
    gPackFields Int
    cc (L1 f a
    l) =
        let (Int
    sc, BitVector (GFieldSize f)
    packed) = Int -> f a -> (Int, BitVector (GFieldSize f))
    forall a. Int -> f a -> (Int, BitVector (GFieldSize f))
    forall (f :: Type -> Type) a.
    GBitPack f =>
    Int -> f a -> (Int, BitVector (GFieldSize f))
    gPackFields Int
    cc f a
    l in
        let padding :: BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize f)
    padding = BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize f)
    forall (n :: Natural). KnownNat n => BitVector n
    undefined# :: BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize f) in
        (Int
    sc, BitVector (GFieldSize f)
    packed BitVector (GFieldSize f)
    -> BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize f)
    -> BitVector
         (GFieldSize f + (Max (GFieldSize f) (GFieldSize g) - GFieldSize f))
    forall (m :: Natural) (n :: Natural).
    KnownNat m =>
    BitVector n -> BitVector m -> BitVector (n + m)
    ++# BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize f)
    padding)
      gPackFields Int
    cc (R1 g a
    r) =
        let cLeft :: Int
    cLeft = SNat (GConstructorCount f) -> Int
    forall a (n :: Natural). Num a => SNat n -> a
    snatToNum (forall (n :: Natural). KnownNat n => SNat n
    SNat @(GConstructorCount f)) in
        let (Int
    sc, BitVector (GFieldSize g)
    packed) = Int -> g a -> (Int, BitVector (GFieldSize g))
    forall a. Int -> g a -> (Int, BitVector (GFieldSize g))
    forall (f :: Type -> Type) a.
    GBitPack f =>
    Int -> f a -> (Int, BitVector (GFieldSize f))
    gPackFields (Int
    cc Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    cLeft) g a
    r in
        let padding :: BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize g)
    padding = BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize g)
    forall (n :: Natural). KnownNat n => BitVector n
    undefined# :: BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize g) in
        (Int
    sc, BitVector (GFieldSize g)
    packed BitVector (GFieldSize g)
    -> BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize g)
    -> BitVector
         (GFieldSize g + (Max (GFieldSize f) (GFieldSize g) - GFieldSize g))
    forall (m :: Natural) (n :: Natural).
    KnownNat m =>
    BitVector n -> BitVector m -> BitVector (n + m)
    ++# BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize g)
    padding)

      gUnpack :: forall a.
    Int -> Int -> BitVector (GFieldSize (f :+: g)) -> (:+:) f g a
    gUnpack Int
    c Int
    cc BitVector (GFieldSize (f :+: g))
    b =
        let cLeft :: Int
    cLeft = SNat (GConstructorCount f) -> Int
    forall a (n :: Natural). Num a => SNat n -> a
    snatToNum (forall (n :: Natural). KnownNat n => SNat n
    SNat @(GConstructorCount f)) in
        if Int
    c Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    cc Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    cLeft then
          f a -> (:+:) f g a
    forall k (f :: k -> Type) (g :: k -> Type) (p :: k).
    f p -> (:+:) f g p
    L1 (Int -> Int -> BitVector (GFieldSize f) -> f a
    forall a. Int -> Int -> BitVector (GFieldSize f) -> f a
    forall (f :: Type -> Type) a.
    GBitPack f =>
    Int -> Int -> BitVector (GFieldSize f) -> f a
    gUnpack Int
    c Int
    cc BitVector (GFieldSize f)
    f)
        else
          g a -> (:+:) f g a
    forall k (f :: k -> Type) (g :: k -> Type) (p :: k).
    g p -> (:+:) f g p
    R1 (Int -> Int -> BitVector (GFieldSize g) -> g a
    forall a. Int -> Int -> BitVector (GFieldSize g) -> g a
    forall (f :: Type -> Type) a.
    GBitPack f =>
    Int -> Int -> BitVector (GFieldSize f) -> f a
    gUnpack Int
    c (Int
    cc Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    cLeft) BitVector (GFieldSize g)
    g)

       where
        -- It's a thing of beauty, if I may say so myself!
        (BitVector (GFieldSize f)
    f, BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize f)
    _ :: BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize f)) = BitVector
      (GFieldSize f + (Max (GFieldSize f) (GFieldSize g) - GFieldSize f))
    -> (BitVector (GFieldSize f),
        BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize f))
    forall (n :: Natural) (m :: Natural).
    KnownNat n =>
    BitVector (m + n) -> (BitVector m, BitVector n)
    split# BitVector
      (GFieldSize f + (Max (GFieldSize f) (GFieldSize g) - GFieldSize f))
    BitVector (GFieldSize (f :+: g))
    b
        (BitVector (GFieldSize g)
    g, BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize g)
    _ :: BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize g)) = BitVector
      (GFieldSize g + (Max (GFieldSize f) (GFieldSize g) - GFieldSize g))
    -> (BitVector (GFieldSize g),
        BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize g))
    forall (n :: Natural) (m :: Natural).
    KnownNat n =>
    BitVector (m + n) -> (BitVector m, BitVector n)
    split# BitVector
      (GFieldSize g + (Max (GFieldSize f) (GFieldSize g) - GFieldSize g))
    BitVector (GFieldSize (f :+: g))
    b

    instance (KnownNat (GFieldSize g), KnownNat (GFieldSize f), GBitPack f, GBitPack g) => GBitPack (f :*: g) where
      type GFieldSize (f :*: g) = GFieldSize f + GFieldSize g
      type GConstructorCount (f :*: g) = 1

      gPackFields :: forall a.
    Int -> (:*:) f g a -> (Int, BitVector (GFieldSize (f :*: g)))
    gPackFields Int
    cc (:*:) f g a
    fg =
        (Int
    cc, ((:*:) f g a -> BitVector (GFieldSize f + GFieldSize g))
    -> (:*:) f g a -> BitVector (GFieldSize f + GFieldSize g)
    forall (n :: Natural) a.
    KnownNat n =>
    (a -> BitVector n) -> a -> BitVector n
    packXWith (:*:) f g a -> BitVector (GFieldSize f + GFieldSize g)
    go (:*:) f g a
    fg)
       where
        go :: (:*:) f g a -> BitVector (GFieldSize f + GFieldSize g)
    go (f a
    l0 :*: g a
    r0) =
          let (Int
    _, BitVector (GFieldSize f)
    l1) = Int -> f a -> (Int, BitVector (GFieldSize f))
    forall a. Int -> f a -> (Int, BitVector (GFieldSize f))
    forall (f :: Type -> Type) a.
    GBitPack f =>
    Int -> f a -> (Int, BitVector (GFieldSize f))
    gPackFields Int
    cc f a
    l0 in
          let (Int
    _, BitVector (GFieldSize g)
    r1) = Int -> g a -> (Int, BitVector (GFieldSize g))
    forall a. Int -> g a -> (Int, BitVector (GFieldSize g))
    forall (f :: Type -> Type) a.
    GBitPack f =>
    Int -> f a -> (Int, BitVector (GFieldSize f))
    gPackFields Int
    cc g a
    r0 in
          BitVector (GFieldSize f)
    l1 BitVector (GFieldSize f)
    -> BitVector (GFieldSize g)
    -> BitVector (GFieldSize f + GFieldSize g)
    forall (m :: Natural) (n :: Natural).
    KnownNat m =>
    BitVector n -> BitVector m -> BitVector (n + m)
    ++# BitVector (GFieldSize g)
    r1

      gUnpack :: forall a.
    Int -> Int -> BitVector (GFieldSize (f :*: g)) -> (:*:) f g a
    gUnpack Int
    c Int
    cc BitVector (GFieldSize (f :*: g))
    b =
        Int -> Int -> BitVector (GFieldSize f) -> f a
    forall a. Int -> Int -> BitVector (GFieldSize f) -> f a
    forall (f :: Type -> Type) a.
    GBitPack f =>
    Int -> Int -> BitVector (GFieldSize f) -> f a
    gUnpack Int
    c Int
    cc BitVector (GFieldSize f)
    front f a -> g a -> (:*:) f g a
    forall k (f :: k -> Type) (g :: k -> Type) (p :: k).
    f p -> g p -> (:*:) f g p
    :*: Int -> Int -> BitVector (GFieldSize g) -> g a
    forall a. Int -> Int -> BitVector (GFieldSize g) -> g a
    forall (f :: Type -> Type) a.
    GBitPack f =>
    Int -> Int -> BitVector (GFieldSize f) -> f a
    gUnpack Int
    c Int
    cc BitVector (GFieldSize g)
    back
       where
        (BitVector (GFieldSize f)
    front, BitVector (GFieldSize g)
    back) = BitVector (GFieldSize f + GFieldSize g)
    -> (BitVector (GFieldSize f), BitVector (GFieldSize g))
    forall (n :: Natural) (m :: Natural).
    KnownNat n =>
    BitVector (m + n) -> (BitVector m, BitVector n)
    split# BitVector (GFieldSize f + GFieldSize g)
    BitVector (GFieldSize (f :*: g))
    b

    instance BitPack c => GBitPack (K1 i c) where
      type GFieldSize (K1 i c) = BitSize c
      type GConstructorCount (K1 i c)  = 1

      gPackFields :: forall a. Int -> K1 i c a -> (Int, BitVector (GFieldSize (K1 i c)))
    gPackFields Int
    cc (K1 c
    i) = (Int
    cc, c -> BitVector (BitSize c)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack c
    i)
      gUnpack :: forall a. Int -> Int -> BitVector (GFieldSize (K1 i c)) -> K1 i c a
    gUnpack Int
    _c Int
    _cc BitVector (GFieldSize (K1 i c))
    b      = c -> K1 i c a
    forall k i c (p :: k). c -> K1 i c p
    K1 (BitVector (BitSize c) -> c
    forall a. BitPack a => BitVector (BitSize a) -> a
    unpack BitVector (GFieldSize (K1 i c))
    BitVector (BitSize c)
    b)

    instance GBitPack U1 where
      type GFieldSize U1 = 0
      type GConstructorCount U1 = 1

      gPackFields :: forall a. Int -> U1 a -> (Int, BitVector (GFieldSize U1))
    gPackFields Int
    cc U1 a
    U1 = (Int
    cc, BitVector 0
    BitVector (GFieldSize U1)
    0)
      gUnpack :: forall a. Int -> Int -> BitVector (GFieldSize U1) -> U1 a
    gUnpack Int
    _c Int
    _cc BitVector (GFieldSize U1)
    _b = U1 a
    forall k (p :: k). U1 p
    U1

    -- Instances derived using Generic
    instance BitPack Ordering

    instance ( BitPack a
             , BitPack b
             ) => BitPack (Either a b)

    instance BitPack a => BitPack (Maybe a)

    instance BitPack a => BitPack (Complex a)
    instance BitPack a => BitPack (Down a)

    instance BitPack a => BitPack (Identity a)
    instance BitPack a => BitPack (Const a b)
    instance (BitPack (f a), BitPack (g a)) => BitPack (Product f g a)
    instance (BitPack (f a), BitPack (g a)) => BitPack (Sum f g a)
    instance BitPack (f (g a)) => BitPack (Compose f g a)

    -- | Zero-extend a 'Bool'ean value to a 'BitVector' of the appropriate size.
    --
    -- >>> boolToBV True :: BitVector 6
    -- 0b00_0001
    -- >>> boolToBV False :: BitVector 6
    -- 0b00_0000
    boolToBV :: KnownNat n => Bool -> BitVector (n + 1)
    boolToBV :: forall (n :: Natural). KnownNat n => Bool -> BitVector (n + 1)
    boolToBV = BitVector 1 -> BitVector (n + 1)
    forall (a :: Natural) (b :: Natural).
    (KnownNat a, KnownNat b) =>
    BitVector a -> BitVector (b + a)
    forall (f :: Natural -> Type) (a :: Natural) (b :: Natural).
    (Resize f, KnownNat a, KnownNat b) =>
    f a -> f (b + a)
    zeroExtend (BitVector 1 -> BitVector (n + 1))
    -> (Bool -> BitVector 1) -> Bool -> BitVector (n + 1)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Bool -> BitVector 1
    Bool -> BitVector (BitSize Bool)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack

    -- | Convert a Bool to a Bit
    boolToBit :: Bool -> Bit
    boolToBit :: Bool -> Bit
    boolToBit = Bool -> Bit
    forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
    bitCoerce

    -- | Convert a Bit to a Bool
    bitToBool :: Bit -> Bool
    bitToBool :: Bit -> Bool
    bitToBool = Bit -> Bool
    forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
    bitCoerce

    -- Derive the BitPack instance for tuples of size 3 to maxTupleSize
    deriveBitPackTuples ''BitPack ''BitSize 'pack 'unpack