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

    {-# LANGUAGE FlexibleContexts #-}

    {-# LANGUAGE Trustworthy #-}

    {-# OPTIONS_HADDOCK show-extensions #-}

    module Clash.Class.BitPack.BitReduction where

    import Clash.Class.BitPack.Internal   (BitPack (..))
    import Clash.Sized.Internal.BitVector (Bit, reduceAnd#, reduceOr#, reduceXor#)

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

    {-# INLINE reduceAnd #-}
    -- | Are all bits set to '1'?
    --
    -- >>> pack (-2 :: Signed 6)
    -- 0b11_1110
    -- >>> reduceAnd (-2 :: Signed 6)
    -- 0
    -- >>> pack (-1 :: Signed 6)
    -- 0b11_1111
    -- >>> reduceAnd (-1 :: Signed 6)
    -- 1
    --
    -- Zero width types will evaluate to '1':
    --
    -- >>> reduceAnd (0 :: Unsigned 0)
    -- 1
    reduceAnd :: BitPack a => a -> Bit
    reduceAnd :: forall a. BitPack a => a -> Bit
    reduceAnd a
    v = BitVector (BitSize a) -> Bit
    forall (n :: Nat). KnownNat n => BitVector n -> Bit
    reduceAnd# (a -> BitVector (BitSize a)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack a
    v)

    {-# INLINE reduceOr #-}
    -- | Is there at least one bit set to '1'?
    --
    -- >>> pack (5 :: Signed 6)
    -- 0b00_0101
    -- >>> reduceOr (5 :: Signed 6)
    -- 1
    -- >>> pack (0 :: Signed 6)
    -- 0b00_0000
    -- >>> reduceOr (0 :: Signed 6)
    -- 0
    --
    -- Zero width types will evaluate to '0':
    --
    -- >>> reduceOr (0 :: Unsigned 0)
    -- 0
    reduceOr :: BitPack a => a -> Bit
    reduceOr :: forall a. BitPack a => a -> Bit
    reduceOr a
    v = BitVector (BitSize a) -> Bit
    forall (n :: Nat). KnownNat n => BitVector n -> Bit
    reduceOr# (a -> BitVector (BitSize a)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack a
    v)

    {-# INLINE reduceXor #-}
    -- | Is the number of bits set to '1' uneven?
    --
    -- >>> pack (5 :: Signed 6)
    -- 0b00_0101
    -- >>> reduceXor (5 :: Signed 6)
    -- 0
    -- >>> pack (28 :: Signed 6)
    -- 0b01_1100
    -- >>> reduceXor (28 :: Signed 6)
    -- 1
    -- >>> pack (-5 :: Signed 6)
    -- 0b11_1011
    -- >>> reduceXor (-5 :: Signed 6)
    -- 1
    --
    -- Zero width types will evaluate to '0':
    --
    -- >>> reduceXor (0 :: Unsigned 0)
    -- 0
    reduceXor :: BitPack a => a -> Bit
    reduceXor :: forall a. BitPack a => a -> Bit
    reduceXor a
    v = BitVector (BitSize a) -> Bit
    forall (n :: Nat). KnownNat n => BitVector n -> Bit
    reduceXor# (a -> BitVector (BitSize a)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack a
    v)