{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}

module Grisette.Core.Data.Class.SymRotate
  ( SymRotate (..),
    DefaultFiniteBitsSymRotate (..),
  )
where

import Data.Bits (Bits (isSigned, rotate), FiniteBits (finiteBitSize))
import Data.Int (Int16, Int32, Int64, Int8)
import Data.Word (Word16, Word32, Word64, Word8)

class (Bits a) => SymRotate a where
  symRotate :: a -> a -> a

instance SymRotate Int where
  symRotate :: Int -> Int -> Int
symRotate = Int -> Int -> Int
forall a. Bits a => a -> Int -> a
rotate

newtype DefaultFiniteBitsSymRotate a = DefaultFiniteBitsSymRotate
  { forall a. DefaultFiniteBitsSymRotate a -> a
unDefaultFiniteBitsSymRotate :: a
  }
  deriving newtype (DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> Bool
(DefaultFiniteBitsSymRotate a
 -> DefaultFiniteBitsSymRotate a -> Bool)
-> (DefaultFiniteBitsSymRotate a
    -> DefaultFiniteBitsSymRotate a -> Bool)
-> Eq (DefaultFiniteBitsSymRotate a)
forall a.
Eq a =>
DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a.
Eq a =>
DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> Bool
== :: DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> Bool
$c/= :: forall a.
Eq a =>
DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> Bool
/= :: DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> Bool
Eq, Eq (DefaultFiniteBitsSymRotate a)
DefaultFiniteBitsSymRotate a
Eq (DefaultFiniteBitsSymRotate a) =>
(DefaultFiniteBitsSymRotate a
 -> DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a
    -> DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a
    -> DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a
    -> Int -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a
    -> Int -> DefaultFiniteBitsSymRotate a)
-> DefaultFiniteBitsSymRotate a
-> (Int -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a
    -> Int -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a
    -> Int -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a
    -> Int -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a -> Int -> Bool)
-> (DefaultFiniteBitsSymRotate a -> Maybe Int)
-> (DefaultFiniteBitsSymRotate a -> Int)
-> (DefaultFiniteBitsSymRotate a -> Bool)
-> (DefaultFiniteBitsSymRotate a
    -> Int -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a
    -> Int -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a
    -> Int -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a
    -> Int -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a
    -> Int -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a
    -> Int -> DefaultFiniteBitsSymRotate a)
-> (DefaultFiniteBitsSymRotate a -> Int)
-> Bits (DefaultFiniteBitsSymRotate a)
Int -> DefaultFiniteBitsSymRotate a
DefaultFiniteBitsSymRotate a -> Bool
DefaultFiniteBitsSymRotate a -> Int
DefaultFiniteBitsSymRotate a -> Maybe Int
DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a
DefaultFiniteBitsSymRotate a -> Int -> Bool
DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a
forall a.
Eq a =>
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> a
-> (Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> Bool)
-> (a -> Maybe Int)
-> (a -> Int)
-> (a -> Bool)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int)
-> Bits a
forall a. Bits a => Eq (DefaultFiniteBitsSymRotate a)
forall a. Bits a => DefaultFiniteBitsSymRotate a
forall a. Bits a => Int -> DefaultFiniteBitsSymRotate a
forall a. Bits a => DefaultFiniteBitsSymRotate a -> Bool
forall a. Bits a => DefaultFiniteBitsSymRotate a -> Int
forall a. Bits a => DefaultFiniteBitsSymRotate a -> Maybe Int
forall a.
Bits a =>
DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a
forall a. Bits a => DefaultFiniteBitsSymRotate a -> Int -> Bool
forall a.
Bits a =>
DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
forall a.
Bits a =>
DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a
$c.&. :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a
.&. :: DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a
$c.|. :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a
.|. :: DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a
$cxor :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a
xor :: DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a
$ccomplement :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a
complement :: DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a
$cshift :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
shift :: DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
$crotate :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
rotate :: DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
$czeroBits :: forall a. Bits a => DefaultFiniteBitsSymRotate a
zeroBits :: DefaultFiniteBitsSymRotate a
$cbit :: forall a. Bits a => Int -> DefaultFiniteBitsSymRotate a
bit :: Int -> DefaultFiniteBitsSymRotate a
$csetBit :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
setBit :: DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
$cclearBit :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
clearBit :: DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
$ccomplementBit :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
complementBit :: DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
$ctestBit :: forall a. Bits a => DefaultFiniteBitsSymRotate a -> Int -> Bool
testBit :: DefaultFiniteBitsSymRotate a -> Int -> Bool
$cbitSizeMaybe :: forall a. Bits a => DefaultFiniteBitsSymRotate a -> Maybe Int
bitSizeMaybe :: DefaultFiniteBitsSymRotate a -> Maybe Int
$cbitSize :: forall a. Bits a => DefaultFiniteBitsSymRotate a -> Int
bitSize :: DefaultFiniteBitsSymRotate a -> Int
$cisSigned :: forall a. Bits a => DefaultFiniteBitsSymRotate a -> Bool
isSigned :: DefaultFiniteBitsSymRotate a -> Bool
$cshiftL :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
shiftL :: DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
$cunsafeShiftL :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
unsafeShiftL :: DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
$cshiftR :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
shiftR :: DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
$cunsafeShiftR :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
unsafeShiftR :: DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
$crotateL :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
rotateL :: DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
$crotateR :: forall a.
Bits a =>
DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
rotateR :: DefaultFiniteBitsSymRotate a -> Int -> DefaultFiniteBitsSymRotate a
$cpopCount :: forall a. Bits a => DefaultFiniteBitsSymRotate a -> Int
popCount :: DefaultFiniteBitsSymRotate a -> Int
Bits)

instance
  (Integral a, FiniteBits a) =>
  SymRotate (DefaultFiniteBitsSymRotate a)
  where
  symRotate :: DefaultFiniteBitsSymRotate a
-> DefaultFiniteBitsSymRotate a -> DefaultFiniteBitsSymRotate a
symRotate (DefaultFiniteBitsSymRotate a
a) (DefaultFiniteBitsSymRotate a
s)
    | a -> Bool
forall a. Bits a => a -> Bool
isSigned a
a = a -> DefaultFiniteBitsSymRotate a
forall a. a -> DefaultFiniteBitsSymRotate a
DefaultFiniteBitsSymRotate (a -> DefaultFiniteBitsSymRotate a)
-> a -> DefaultFiniteBitsSymRotate a
forall a b. (a -> b) -> a -> b
$ a -> a -> a
symRotateSigned a
a a
s
    | Bool
otherwise = a -> DefaultFiniteBitsSymRotate a
forall a. a -> DefaultFiniteBitsSymRotate a
DefaultFiniteBitsSymRotate (a -> DefaultFiniteBitsSymRotate a)
-> a -> DefaultFiniteBitsSymRotate a
forall a b. (a -> b) -> a -> b
$ a -> a -> a
symRotateUnsigned a
a a
s
    where
      symRotateUnsigned :: a -> a -> a
      symRotateUnsigned :: a -> a -> a
symRotateUnsigned a
a a
s =
        a -> Int -> a
forall a. Bits a => a -> Int -> a
rotate a
a (a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a
s a -> a -> a
forall a. Integral a => a -> a -> a
`mod` Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a -> Int
forall b. FiniteBits b => b -> Int
finiteBitSize a
a)))
      symRotateSigned :: a -> a -> a
      symRotateSigned :: a -> a -> a
symRotateSigned a
a a
s
        | a -> Int
forall b. FiniteBits b => b -> Int
finiteBitSize a
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 = a
a
        | a -> Int
forall b. FiniteBits b => b -> Int
finiteBitSize a
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2 = a -> Int -> a
forall a. Bits a => a -> Int -> a
rotate a
a (a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
s)
        | Bool
otherwise =
            a -> Int -> a
forall a. Bits a => a -> Int -> a
rotate a
a (a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a
s a -> a -> a
forall a. Integral a => a -> a -> a
`mod` Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a -> Int
forall b. FiniteBits b => b -> Int
finiteBitSize a
a)))

deriving via (DefaultFiniteBitsSymRotate Int8) instance SymRotate Int8

deriving via (DefaultFiniteBitsSymRotate Int16) instance SymRotate Int16

deriving via (DefaultFiniteBitsSymRotate Int32) instance SymRotate Int32

deriving via (DefaultFiniteBitsSymRotate Int64) instance SymRotate Int64

deriving via (DefaultFiniteBitsSymRotate Word8) instance SymRotate Word8

deriving via (DefaultFiniteBitsSymRotate Word16) instance SymRotate Word16

deriving via (DefaultFiniteBitsSymRotate Word32) instance SymRotate Word32

deriving via (DefaultFiniteBitsSymRotate Word64) instance SymRotate Word64

deriving via (DefaultFiniteBitsSymRotate Word) instance SymRotate Word