    {-|
    Copyright  :  (C) 2019, QBayLogic
    License    :  BSD2 (see the file LICENSE)
    Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>
    -}

    {-# LANGUAGE CPP #-}
    {-# LANGUAGE FlexibleContexts #-}

    {-# 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.Parity
      ( Parity (..) )
    where

    import Prelude hiding                 (even, odd)

    import Data.Int
    import Data.Word
    import Foreign.C.Types                (CUShort)
    import GHC.TypeLits                   (KnownNat)

    import Clash.Class.BitPack            (pack)
    import Clash.Sized.Internal.BitVector (BitVector, high, low, lsb#)
    import Clash.Promoted.Nat             (SNat(..), snatToNum)

    {- $setup
    >>> :m -Prelude
    >>> import Clash.Prelude
    >>> import Clash.Class.Parity
    -}

    -- | Determine whether value is odd or even
    class Parity a where
      -- | Check if value is even
      --
      -- >>> even (4 :: Unsigned 4)
      -- True
      even :: a -> Bool
      even = Bool -> Bool
    not (Bool -> Bool) -> (a -> Bool) -> a -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Bool
    forall a. Parity a => a -> Bool
    odd

      -- | Check if value is odd
      --
      -- >>> odd (4 :: Unsigned 4)
      -- False
      odd :: a -> Bool
      odd = Bool -> Bool
    not (Bool -> Bool) -> (a -> Bool) -> a -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Bool
    forall a. Parity a => a -> Bool
    even
      {-# MINIMAL even | odd #-}

    instance Parity Integer
      where
        even :: Integer -> Bool
    even Integer
    a = Integer
    a Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `mod` Integer
    2 Integer -> Integer -> Bool
    forall a. Eq a => a -> a -> Bool
    == Integer
    0
        odd :: Integer -> Bool
    odd Integer
    a = Integer
    a Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `mod` Integer
    2 Integer -> Integer -> Bool
    forall a. Eq a => a -> a -> Bool
    == Integer
    1

    instance KnownNat n => Parity (BitVector n) where
      even :: BitVector n -> Bool
    even BitVector n
    a =
        case forall a (n :: Nat). Num a => SNat n -> a
    snatToNum @Integer (forall (n :: Nat). KnownNat n => SNat n
    SNat @n) of
          Integer
    0 -> Bool
    True
          Integer
    _ -> (Bit -> Bit -> Bool
    forall a. Eq a => a -> a -> Bool
    ==Bit
    low) (Bit -> Bool) -> Bit -> Bool
    forall a b. (a -> b) -> a -> b
    $ BitVector n -> Bit
    forall (n :: Nat). BitVector n -> Bit
    lsb# BitVector n
    a
      odd :: BitVector n -> Bool
    odd BitVector n
    a =
        case forall a (n :: Nat). Num a => SNat n -> a
    snatToNum @Integer (forall (n :: Nat). KnownNat n => SNat n
    SNat @n) of
          Integer
    0 -> Bool
    False
          Integer
    _ -> (Bit -> Bit -> Bool
    forall a. Eq a => a -> a -> Bool
    ==Bit
    high) (Bit -> Bool) -> Bit -> Bool
    forall a b. (a -> b) -> a -> b
    $ BitVector n -> Bit
    forall (n :: Nat). BitVector n -> Bit
    lsb# BitVector n
    a

    instance Parity Bool where
      even :: Bool -> Bool
    even = BitVector 1 -> Bool
    forall a. Parity a => a -> Bool
    even (BitVector 1 -> Bool) -> (Bool -> BitVector 1) -> Bool -> Bool
    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
      odd :: Bool -> Bool
    odd = BitVector 1 -> Bool
    forall a. Parity a => a -> Bool
    odd (BitVector 1 -> Bool) -> (Bool -> BitVector 1) -> Bool -> Bool
    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

    instance Parity CUShort where
      even :: CUShort -> Bool
    even = BitVector 16 -> Bool
    forall a. Parity a => a -> Bool
    even (BitVector 16 -> Bool)
    -> (CUShort -> BitVector 16) -> CUShort -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CUShort -> BitVector 16
    CUShort -> BitVector (BitSize CUShort)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack
      odd :: CUShort -> Bool
    odd = BitVector 16 -> Bool
    forall a. Parity a => a -> Bool
    odd (BitVector 16 -> Bool)
    -> (CUShort -> BitVector 16) -> CUShort -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CUShort -> BitVector 16
    CUShort -> BitVector (BitSize CUShort)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack

    instance Parity Word where
      even :: Word -> Bool
    even = BitVector 64 -> Bool
    forall a. Parity a => a -> Bool
    even (BitVector 64 -> Bool) -> (Word -> BitVector 64) -> Word -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word -> BitVector 64
    Word -> BitVector (BitSize Word)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack
      odd :: Word -> Bool
    odd = BitVector 64 -> Bool
    forall a. Parity a => a -> Bool
    odd (BitVector 64 -> Bool) -> (Word -> BitVector 64) -> Word -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word -> BitVector 64
    Word -> BitVector (BitSize Word)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack

    instance Parity Word8 where
      even :: Word8 -> Bool
    even = BitVector 8 -> Bool
    forall a. Parity a => a -> Bool
    even (BitVector 8 -> Bool) -> (Word8 -> BitVector 8) -> Word8 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> BitVector 8
    Word8 -> BitVector (BitSize Word8)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack
      odd :: Word8 -> Bool
    odd = BitVector 8 -> Bool
    forall a. Parity a => a -> Bool
    odd (BitVector 8 -> Bool) -> (Word8 -> BitVector 8) -> Word8 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> BitVector 8
    Word8 -> BitVector (BitSize Word8)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack

    instance Parity Word16 where
      even :: Word16 -> Bool
    even = BitVector 16 -> Bool
    forall a. Parity a => a -> Bool
    even (BitVector 16 -> Bool)
    -> (Word16 -> BitVector 16) -> Word16 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word16 -> BitVector 16
    Word16 -> BitVector (BitSize Word16)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack
      odd :: Word16 -> Bool
    odd = BitVector 16 -> Bool
    forall a. Parity a => a -> Bool
    odd (BitVector 16 -> Bool)
    -> (Word16 -> BitVector 16) -> Word16 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word16 -> BitVector 16
    Word16 -> BitVector (BitSize Word16)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack

    instance Parity Word32 where
      even :: Word32 -> Bool
    even = BitVector 32 -> Bool
    forall a. Parity a => a -> Bool
    even (BitVector 32 -> Bool)
    -> (Word32 -> BitVector 32) -> Word32 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word32 -> BitVector 32
    Word32 -> BitVector (BitSize Word32)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack
      odd :: Word32 -> Bool
    odd = BitVector 32 -> Bool
    forall a. Parity a => a -> Bool
    odd (BitVector 32 -> Bool)
    -> (Word32 -> BitVector 32) -> Word32 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word32 -> BitVector 32
    Word32 -> BitVector (BitSize Word32)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack

    instance Parity Word64 where
      even :: Word64 -> Bool
    even = BitVector 64 -> Bool
    forall a. Parity a => a -> Bool
    even (BitVector 64 -> Bool)
    -> (Word64 -> BitVector 64) -> Word64 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word64 -> BitVector 64
    Word64 -> BitVector (BitSize Word64)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack
      odd :: Word64 -> Bool
    odd = BitVector 64 -> Bool
    forall a. Parity a => a -> Bool
    odd (BitVector 64 -> Bool)
    -> (Word64 -> BitVector 64) -> Word64 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word64 -> BitVector 64
    Word64 -> BitVector (BitSize Word64)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack

    instance Parity Int where
      even :: Int -> Bool
    even = BitVector 64 -> Bool
    forall a. Parity a => a -> Bool
    even (BitVector 64 -> Bool) -> (Int -> BitVector 64) -> Int -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> BitVector 64
    Int -> BitVector (BitSize Int)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack
      odd :: Int -> Bool
    odd = BitVector 64 -> Bool
    forall a. Parity a => a -> Bool
    odd (BitVector 64 -> Bool) -> (Int -> BitVector 64) -> Int -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> BitVector 64
    Int -> BitVector (BitSize Int)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack

    instance Parity Int8 where
      even :: Int8 -> Bool
    even = BitVector 8 -> Bool
    forall a. Parity a => a -> Bool
    even (BitVector 8 -> Bool) -> (Int8 -> BitVector 8) -> Int8 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int8 -> BitVector 8
    Int8 -> BitVector (BitSize Int8)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack
      odd :: Int8 -> Bool
    odd = BitVector 8 -> Bool
    forall a. Parity a => a -> Bool
    odd (BitVector 8 -> Bool) -> (Int8 -> BitVector 8) -> Int8 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int8 -> BitVector 8
    Int8 -> BitVector (BitSize Int8)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack

    instance Parity Int16 where
      even :: Int16 -> Bool
    even = BitVector 16 -> Bool
    forall a. Parity a => a -> Bool
    even (BitVector 16 -> Bool) -> (Int16 -> BitVector 16) -> Int16 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int16 -> BitVector 16
    Int16 -> BitVector (BitSize Int16)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack
      odd :: Int16 -> Bool
    odd = BitVector 16 -> Bool
    forall a. Parity a => a -> Bool
    odd (BitVector 16 -> Bool) -> (Int16 -> BitVector 16) -> Int16 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int16 -> BitVector 16
    Int16 -> BitVector (BitSize Int16)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack

    instance Parity Int32 where
      even :: Int32 -> Bool
    even = BitVector 32 -> Bool
    forall a. Parity a => a -> Bool
    even (BitVector 32 -> Bool) -> (Int32 -> BitVector 32) -> Int32 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int32 -> BitVector 32
    Int32 -> BitVector (BitSize Int32)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack
      odd :: Int32 -> Bool
    odd = BitVector 32 -> Bool
    forall a. Parity a => a -> Bool
    odd (BitVector 32 -> Bool) -> (Int32 -> BitVector 32) -> Int32 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int32 -> BitVector 32
    Int32 -> BitVector (BitSize Int32)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack

    instance Parity Int64 where
      even :: Int64 -> Bool
    even = BitVector 64 -> Bool
    forall a. Parity a => a -> Bool
    even (BitVector 64 -> Bool) -> (Int64 -> BitVector 64) -> Int64 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int64 -> BitVector 64
    Int64 -> BitVector (BitSize Int64)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack
      odd :: Int64 -> Bool
    odd = BitVector 64 -> Bool
    forall a. Parity a => a -> Bool
    odd (BitVector 64 -> Bool) -> (Int64 -> BitVector 64) -> Int64 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int64 -> BitVector 64
    Int64 -> BitVector (BitSize Int64)
    forall a. BitPack a => a -> BitVector (BitSize a)
    pack