{-# LANGUAGE CPP                #-}
{-# LANGUAGE MagicHash          #-}
{-# LANGUAGE UnboxedTuples      #-}
{-# LANGUAGE DeriveDataTypeable #-}
module Basement.Types.Word256
    ( Word256(..)
    , (+)
    , (-)
    , (*)
    , quot
    , rem
    , bitwiseAnd
    , bitwiseOr
    , bitwiseXor
    , complement
    , shiftL
    , shiftR
    , rotateL
    , rotateR
    , popCount
    , fromNatural
    ) where

import           GHC.Prim
import           GHC.Word
import           GHC.Types
import qualified Prelude (fromInteger, show, Num(..), quot, rem, mod)
import           Data.Bits hiding (complement, popCount, bit, testBit
                                  , rotateL, rotateR, shiftL, shiftR)
import qualified Data.Bits as Bits
import           Data.Function (on)
import           Foreign.C
import           Foreign.Ptr
import           Foreign.Storable

import           Basement.Compat.Base
import           Basement.Compat.Natural
import           Basement.Compat.Primitive (bool#)
import           Basement.Numerical.Conversion
import           Basement.Numerical.Number

#include "MachDeps.h"

-- | 256 bits Word
data Word256 = Word256 {-# UNPACK #-} !Word64
                       {-# UNPACK #-} !Word64
                       {-# UNPACK #-} !Word64
                       {-# UNPACK #-} !Word64
    deriving (Word256 -> Word256 -> Bool
(Word256 -> Word256 -> Bool)
-> (Word256 -> Word256 -> Bool) -> Eq Word256
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Word256 -> Word256 -> Bool
$c/= :: Word256 -> Word256 -> Bool
== :: Word256 -> Word256 -> Bool
$c== :: Word256 -> Word256 -> Bool
Eq, Typeable)

instance Show Word256 where
    show :: Word256 -> String
show Word256
w = Natural -> String
forall a. Show a => a -> String
Prelude.show (Word256 -> Natural
forall a. IsNatural a => a -> Natural
toNatural Word256
w)
instance Enum Word256 where
    toEnum :: Int -> Word256
toEnum Int
i = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
0 Word64
0 Word64
0 (Word64 -> Word256) -> Word64 -> Word256
forall a b. (a -> b) -> a -> b
$ Int64 -> Word64
int64ToWord64 (Int -> Int64
intToInt64 Int
i)
    fromEnum :: Word256 -> Int
fromEnum (Word256 Word64
_ Word64
_ Word64
_ Word64
a0) = Word -> Int
wordToInt (Word64 -> Word
word64ToWord Word64
a0)
    succ :: Word256 -> Word256
succ (Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0)
        | Word64
a0 Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
forall a. Bounded a => a
maxBound =
            if Word64
a1 Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
forall a. Bounded a => a
maxBound
                then if Word64
a2 Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
forall a. Bounded a => a
maxBound
                        then Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 (Word64 -> Word64
forall a. Enum a => a -> a
succ Word64
a3) Word64
0 Word64
0 Word64
0
                        else Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
a3 (Word64 -> Word64
forall a. Enum a => a -> a
succ Word64
a2) Word64
0 Word64
0
                else Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
a3 Word64
a2 (Word64 -> Word64
forall a. Enum a => a -> a
succ Word64
a1) Word64
0
        | Bool
otherwise      = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
a3 Word64
a2 Word64
a1        (Word64 -> Word64
forall a. Enum a => a -> a
succ Word64
a0)
    pred :: Word256 -> Word256
pred (Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0)
        | Word64
a0 Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
forall a. Bounded a => a
minBound =
            if Word64
a1 Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
forall a. Bounded a => a
minBound
                then if Word64
a2 Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
forall a. Bounded a => a
minBound
                        then Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 (Word64 -> Word64
forall a. Enum a => a -> a
pred Word64
a3) Word64
forall a. Bounded a => a
maxBound Word64
forall a. Bounded a => a
maxBound Word64
forall a. Bounded a => a
maxBound
                        else Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
a3 (Word64 -> Word64
forall a. Enum a => a -> a
pred Word64
a2) Word64
forall a. Bounded a => a
maxBound Word64
forall a. Bounded a => a
maxBound
                else Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
a3 Word64
a2 (Word64 -> Word64
forall a. Enum a => a -> a
pred Word64
a1) Word64
forall a. Bounded a => a
maxBound
        | Bool
otherwise      = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
a3 Word64
a2 Word64
a1        (Word64 -> Word64
forall a. Enum a => a -> a
pred Word64
a0)
instance Bounded Word256 where
    minBound :: Word256
minBound = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
forall a. Bounded a => a
minBound Word64
forall a. Bounded a => a
minBound Word64
forall a. Bounded a => a
minBound Word64
forall a. Bounded a => a
minBound
    maxBound :: Word256
maxBound = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
forall a. Bounded a => a
maxBound Word64
forall a. Bounded a => a
maxBound Word64
forall a. Bounded a => a
maxBound Word64
forall a. Bounded a => a
maxBound
instance Ord Word256 where
    compare :: Word256 -> Word256 -> Ordering
compare (Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0) (Word256 Word64
b3 Word64
b2 Word64
b1 Word64
b0) =
        Word64 -> Word64 -> Ordering -> Ordering
forall a. Ord a => a -> a -> Ordering -> Ordering
compareEq Word64
a3 Word64
b3 (Ordering -> Ordering) -> Ordering -> Ordering
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> Ordering -> Ordering
forall a. Ord a => a -> a -> Ordering -> Ordering
compareEq Word64
a2 Word64
b2 (Ordering -> Ordering) -> Ordering -> Ordering
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> Ordering -> Ordering
forall a. Ord a => a -> a -> Ordering -> Ordering
compareEq Word64
a1 Word64
b1 (Ordering -> Ordering) -> Ordering -> Ordering
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Word64
a0 Word64
b0
      where compareEq :: a -> a -> Ordering -> Ordering
compareEq a
x a
y Ordering
next =
                case a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare a
x a
y of
                    Ordering
EQ -> Ordering
next
                    Ordering
r  -> Ordering
r
    < :: Word256 -> Word256 -> Bool
(<) (Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0) (Word256 Word64
b3 Word64
b2 Word64
b1 Word64
b0) =
        Word64 -> Word64 -> Bool -> Bool
forall a. Ord a => a -> a -> Bool -> Bool
compareLt Word64
a3 Word64
b3 (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> Bool -> Bool
forall a. Ord a => a -> a -> Bool -> Bool
compareLt Word64
a2 Word64
b2 (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> Bool -> Bool
forall a. Ord a => a -> a -> Bool -> Bool
compareLt Word64
a1 Word64
b1 (Word64
a0 Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
b0)
      where compareLt :: a -> a -> Bool -> Bool
compareLt a
x a
y Bool
next =
                case a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare a
x a
y of
                    Ordering
EQ -> Bool
next
                    Ordering
r  -> Ordering
r Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
LT
instance Storable Word256 where
    sizeOf :: Word256 -> Int
sizeOf Word256
_ = Int
32
    alignment :: Word256 -> Int
alignment Word256
_ = Int
32
    peek :: Ptr Word256 -> IO Word256
peek Ptr Word256
p = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 (Word64 -> Word64 -> Word64 -> Word64 -> Word256)
-> IO Word64 -> IO (Word64 -> Word64 -> Word64 -> Word256)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Word64 -> IO Word64
forall a. Storable a => Ptr a -> IO a
peek (Ptr Word256 -> Ptr Word64
forall a b. Ptr a -> Ptr b
castPtr Ptr Word256
p            )
                     IO (Word64 -> Word64 -> Word64 -> Word256)
-> IO Word64 -> IO (Word64 -> Word64 -> Word256)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr Word64 -> IO Word64
forall a. Storable a => Ptr a -> IO a
peek (Ptr Word256 -> Ptr Any
forall a b. Ptr a -> Ptr b
castPtr Ptr Word256
p Ptr Any -> Int -> Ptr Word64
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
8)
                     IO (Word64 -> Word64 -> Word256)
-> IO Word64 -> IO (Word64 -> Word256)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr Word64 -> IO Word64
forall a. Storable a => Ptr a -> IO a
peek (Ptr Word256 -> Ptr Any
forall a b. Ptr a -> Ptr b
castPtr Ptr Word256
p Ptr Any -> Int -> Ptr Word64
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
16)
                     IO (Word64 -> Word256) -> IO Word64 -> IO Word256
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr Word64 -> IO Word64
forall a. Storable a => Ptr a -> IO a
peek (Ptr Word256 -> Ptr Any
forall a b. Ptr a -> Ptr b
castPtr Ptr Word256
p Ptr Any -> Int -> Ptr Word64
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
24)
    poke :: Ptr Word256 -> Word256 -> IO ()
poke Ptr Word256
p (Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0) = do
        Ptr Word64 -> Word64 -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr Word256 -> Ptr Word64
forall a b. Ptr a -> Ptr b
castPtr Ptr Word256
p             ) Word64
a3
        Ptr Word64 -> Word64 -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr Word256 -> Ptr Any
forall a b. Ptr a -> Ptr b
castPtr Ptr Word256
p Ptr Any -> Int -> Ptr Word64
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
8 ) Word64
a2
        Ptr Word64 -> Word64 -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr Word256 -> Ptr Any
forall a b. Ptr a -> Ptr b
castPtr Ptr Word256
p Ptr Any -> Int -> Ptr Word64
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
16) Word64
a1
        Ptr Word64 -> Word64 -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr Word256 -> Ptr Any
forall a b. Ptr a -> Ptr b
castPtr Ptr Word256
p Ptr Any -> Int -> Ptr Word64
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
24) Word64
a0

instance Integral Word256 where
    fromInteger :: Integer -> Word256
fromInteger = Integer -> Word256
literal
instance HasNegation Word256 where
    negate :: Word256 -> Word256
negate = Word256 -> Word256
complement

instance IsIntegral Word256 where
    toInteger :: Word256 -> Integer
toInteger (Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0) =
        (Word64 -> Integer
forall a. IsIntegral a => a -> Integer
toInteger Word64
a3 Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftL` Int
192) Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
Bits..|.
        (Word64 -> Integer
forall a. IsIntegral a => a -> Integer
toInteger Word64
a2 Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftL` Int
128) Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
Bits..|.
        (Word64 -> Integer
forall a. IsIntegral a => a -> Integer
toInteger Word64
a1 Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftL` Int
64) Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
Bits..|.
        Word64 -> Integer
forall a. IsIntegral a => a -> Integer
toInteger Word64
a0
instance IsNatural Word256 where
    toNatural :: Word256 -> Natural
toNatural (Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0) =
        (Word64 -> Natural
forall a. IsNatural a => a -> Natural
toNatural Word64
a3 Natural -> Int -> Natural
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftL` Int
192) Natural -> Natural -> Natural
forall a. Bits a => a -> a -> a
Bits..|.
        (Word64 -> Natural
forall a. IsNatural a => a -> Natural
toNatural Word64
a2 Natural -> Int -> Natural
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftL` Int
128) Natural -> Natural -> Natural
forall a. Bits a => a -> a -> a
Bits..|.
        (Word64 -> Natural
forall a. IsNatural a => a -> Natural
toNatural Word64
a1 Natural -> Int -> Natural
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftL` Int
64) Natural -> Natural -> Natural
forall a. Bits a => a -> a -> a
Bits..|.
        Word64 -> Natural
forall a. IsNatural a => a -> Natural
toNatural Word64
a0

instance Prelude.Num Word256 where
    abs :: Word256 -> Word256
abs Word256
w = Word256
w
    signum :: Word256 -> Word256
signum w :: Word256
w@(Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0)
        | Word64
a3 Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
0 Bool -> Bool -> Bool
&& Word64
a2 Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
0 Bool -> Bool -> Bool
&& Word64
a1 Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
0 Bool -> Bool -> Bool
&& Word64
a0 Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
0 = Word256
w
        | Bool
otherwise                                = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
0 Word64
0 Word64
0 Word64
1
    fromInteger :: Integer -> Word256
fromInteger = Integer -> Word256
literal
    + :: Word256 -> Word256 -> Word256
(+) = Word256 -> Word256 -> Word256
(+)
    (-) = (-)
    * :: Word256 -> Word256 -> Word256
(*) = Word256 -> Word256 -> Word256
(*)

instance Bits.Bits Word256 where
    .&. :: Word256 -> Word256 -> Word256
(.&.) = Word256 -> Word256 -> Word256
bitwiseAnd
    .|. :: Word256 -> Word256 -> Word256
(.|.) = Word256 -> Word256 -> Word256
bitwiseOr
    xor :: Word256 -> Word256 -> Word256
xor   = Word256 -> Word256 -> Word256
bitwiseXor
    complement :: Word256 -> Word256
complement = Word256 -> Word256
complement
    shiftL :: Word256 -> Int -> Word256
shiftL = Word256 -> Int -> Word256
shiftL
    shiftR :: Word256 -> Int -> Word256
shiftR = Word256 -> Int -> Word256
shiftR
    rotateL :: Word256 -> Int -> Word256
rotateL = Word256 -> Int -> Word256
rotateL
    rotateR :: Word256 -> Int -> Word256
rotateR = Word256 -> Int -> Word256
rotateR
    bitSize :: Word256 -> Int
bitSize Word256
_ = Int
256
    bitSizeMaybe :: Word256 -> Maybe Int
bitSizeMaybe Word256
_ = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
256
    isSigned :: Word256 -> Bool
isSigned Word256
_ = Bool
False
    testBit :: Word256 -> Int -> Bool
testBit = Word256 -> Int -> Bool
testBit
    bit :: Int -> Word256
bit = Int -> Word256
bit
    popCount :: Word256 -> Int
popCount = Word256 -> Int
popCount

-- | Add 2 Word256
(+) :: Word256 -> Word256 -> Word256
#if WORD_SIZE_IN_BITS < 64
(+) = applyBiWordOnNatural (Prelude.+)
#else
+ :: Word256 -> Word256 -> Word256
(+) (Word256 (W64# Word#
a3) (W64# Word#
a2) (W64# Word#
a1) (W64# Word#
a0))
    (Word256 (W64# Word#
b3) (W64# Word#
b2) (W64# Word#
b1) (W64# Word#
b0)) =
    Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 (Word# -> Word64
W64# Word#
s3) (Word# -> Word64
W64# Word#
s2) (Word# -> Word64
W64# Word#
s1) (Word# -> Word64
W64# Word#
s0)
  where
    !(# Word#
c0, Word#
s0 #) = Word# -> Word# -> (# Word#, Word# #)
plusWord2# Word#
a0 Word#
b0
    !(# Word#
c1, Word#
s1 #) = Word# -> Word# -> Word# -> (# Word#, Word# #)
plusWord3# Word#
a1 Word#
b1 Word#
c0
    !(# Word#
c2, Word#
s2 #) = Word# -> Word# -> Word# -> (# Word#, Word# #)
plusWord3# Word#
a2 Word#
b2 Word#
c1
    !s3 :: Word#
s3           = Word# -> Word# -> Word# -> Word#
plusWord3NoCarry# Word#
a3 Word#
b3 Word#
c2

    plusWord3NoCarry# :: Word# -> Word# -> Word# -> Word#
plusWord3NoCarry# Word#
a Word#
b Word#
c = Word# -> Word# -> Word#
plusWord# (Word# -> Word# -> Word#
plusWord# Word#
a Word#
b) Word#
c
    plusWord3# :: Word# -> Word# -> Word# -> (# Word#, Word# #)
plusWord3# Word#
a Word#
b Word#
c
        | Int# -> Bool
bool# (Word# -> Word# -> Int#
eqWord# Word#
carry Word#
0##) = Word# -> Word# -> (# Word#, Word# #)
plusWord2# Word#
x Word#
c
        | Bool
otherwise                 =
            case Word# -> Word# -> (# Word#, Word# #)
plusWord2# Word#
x Word#
c of
                (# Word#
carry2, Word#
x' #)
                    | Int# -> Bool
bool# (Word# -> Word# -> Int#
eqWord# Word#
carry2 Word#
0##) -> (# Word#
carry, Word#
x' #)
                    | Bool
otherwise                  -> (# Word# -> Word# -> Word#
plusWord# Word#
carry Word#
carry2, Word#
x' #)
      where
        (# Word#
carry, Word#
x #) = Word# -> Word# -> (# Word#, Word# #)
plusWord2# Word#
a Word#
b
#endif

-- temporary available until native operation available
applyBiWordOnNatural :: (Natural -> Natural -> Natural)
                     -> Word256
                     -> Word256
                     -> Word256
applyBiWordOnNatural :: (Natural -> Natural -> Natural) -> Word256 -> Word256 -> Word256
applyBiWordOnNatural Natural -> Natural -> Natural
f = (Natural -> Word256
fromNatural (Natural -> Word256) -> (Word256 -> Natural) -> Word256 -> Word256
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
.) ((Word256 -> Natural) -> Word256 -> Word256)
-> (Word256 -> Word256 -> Natural) -> Word256 -> Word256 -> Word256
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Natural -> Natural -> Natural
f (Natural -> Natural -> Natural)
-> (Word256 -> Natural) -> Word256 -> Word256 -> Natural
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Word256 -> Natural
forall a. IsNatural a => a -> Natural
toNatural)

-- | Subtract 2 Word256
(-) :: Word256 -> Word256 -> Word256
(-) Word256
a Word256
b
    | Word256
a Word256 -> Word256 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word256
b    = (Natural -> Natural -> Natural) -> Word256 -> Word256 -> Word256
applyBiWordOnNatural Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
(Prelude.-) Word256
a Word256
b
    | Bool
otherwise = Word256 -> Word256
complement ((Natural -> Natural -> Natural) -> Word256 -> Word256 -> Word256
applyBiWordOnNatural Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
(Prelude.-) Word256
b Word256
a) Word256 -> Word256 -> Word256
+ Word256
1

-- | Multiplication
(*) :: Word256 -> Word256 -> Word256
* :: Word256 -> Word256 -> Word256
(*) = (Natural -> Natural -> Natural) -> Word256 -> Word256 -> Word256
applyBiWordOnNatural Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
(Prelude.*)

-- | Division
quot :: Word256 -> Word256 -> Word256
quot :: Word256 -> Word256 -> Word256
quot = (Natural -> Natural -> Natural) -> Word256 -> Word256 -> Word256
applyBiWordOnNatural Natural -> Natural -> Natural
forall a. Integral a => a -> a -> a
Prelude.quot

-- | Modulo
rem :: Word256 -> Word256 -> Word256
rem :: Word256 -> Word256 -> Word256
rem = (Natural -> Natural -> Natural) -> Word256 -> Word256 -> Word256
applyBiWordOnNatural Natural -> Natural -> Natural
forall a. Integral a => a -> a -> a
Prelude.rem

-- | Bitwise and
bitwiseAnd :: Word256 -> Word256 -> Word256
bitwiseAnd :: Word256 -> Word256 -> Word256
bitwiseAnd (Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0) (Word256 Word64
b3 Word64
b2 Word64
b1 Word64
b0) =
    Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 (Word64
a3 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
Bits..&. Word64
b3) (Word64
a2 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
Bits..&. Word64
b2)  (Word64
a1 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
Bits..&. Word64
b1) (Word64
a0 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
Bits..&. Word64
b0)

-- | Bitwise or
bitwiseOr :: Word256 -> Word256 -> Word256
bitwiseOr :: Word256 -> Word256 -> Word256
bitwiseOr (Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0) (Word256 Word64
b3 Word64
b2 Word64
b1 Word64
b0) =
    Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 (Word64
a3 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
Bits..|. Word64
b3) (Word64
a2 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
Bits..|. Word64
b2)  (Word64
a1 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
Bits..|. Word64
b1) (Word64
a0 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
Bits..|. Word64
b0)

-- | Bitwise xor
bitwiseXor :: Word256 -> Word256 -> Word256
bitwiseXor :: Word256 -> Word256 -> Word256
bitwiseXor (Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0) (Word256 Word64
b3 Word64
b2 Word64
b1 Word64
b0) =
    Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 (Word64
a3 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
`Bits.xor` Word64
b3) (Word64
a2 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
`Bits.xor` Word64
b2)  (Word64
a1 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
`Bits.xor` Word64
b1) (Word64
a0 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
`Bits.xor` Word64
b0)

-- | Bitwise complement
complement :: Word256 -> Word256
complement :: Word256 -> Word256
complement (Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0) =
    Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 (Word64 -> Word64
forall a. Bits a => a -> a
Bits.complement Word64
a3) (Word64 -> Word64
forall a. Bits a => a -> a
Bits.complement Word64
a2) (Word64 -> Word64
forall a. Bits a => a -> a
Bits.complement Word64
a1) (Word64 -> Word64
forall a. Bits a => a -> a
Bits.complement Word64
a0)

-- | Population count
popCount :: Word256 -> Int
popCount :: Word256 -> Int
popCount (Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0) =
    Word64 -> Int
forall a. Bits a => a -> Int
Bits.popCount Word64
a3 Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.+
    Word64 -> Int
forall a. Bits a => a -> Int
Bits.popCount Word64
a2 Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.+
    Word64 -> Int
forall a. Bits a => a -> Int
Bits.popCount Word64
a1 Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.+
    Word64 -> Int
forall a. Bits a => a -> Int
Bits.popCount Word64
a0

-- | Bitwise Shift Left
shiftL :: Word256 -> Int -> Word256
shiftL :: Word256 -> Int -> Word256
shiftL w :: Word256
w@(Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0) Int
n
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
255 = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
0 Word64
0 Word64
0 Word64
0
    | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0           = Word256
w
    | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
64          = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
a2 Word64
a1 Word64
a0 Word64
0
    | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
128         = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
a1 Word64
a0 Word64
0 Word64
0
    | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
192         = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
a0 Word64
0 Word64
0 Word64
0
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
64           = Word64 -> Word64 -> Word64 -> Word64 -> Int -> Word256
mkWordShift Word64
a3 Word64
a2 Word64
a1 Word64
a0 Int
n
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
128          = Word64 -> Word64 -> Word64 -> Word64 -> Int -> Word256
mkWordShift Word64
a2 Word64
a1 Word64
a0 Word64
0  (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
64)
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
192          = Word64 -> Word64 -> Word64 -> Word64 -> Int -> Word256
mkWordShift Word64
a1 Word64
a0 Word64
0  Word64
0  (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
128)
    | Bool
otherwise        = Word64 -> Word64 -> Word64 -> Word64 -> Int -> Word256
mkWordShift Word64
a0 Word64
0  Word64
0  Word64
0  (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
192)
  where
    mkWordShift :: Word64 -> Word64 -> Word64 -> Word64 -> Int -> Word256
    mkWordShift :: Word64 -> Word64 -> Word64 -> Word64 -> Int -> Word256
mkWordShift Word64
w Word64
x Word64
y Word64
z Int
s =
        Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
w Int
s Word64
x Int
s') (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
x Int
s Word64
y Int
s') (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
y Int
s Word64
z Int
s') (Word64
z Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftL` Int
s)
      where s' :: Int
s' = Int -> Int
inv64 Int
s

-- | Bitwise Shift Right
shiftR :: Word256 -> Int -> Word256
shiftR :: Word256 -> Int -> Word256
shiftR w :: Word256
w@(Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0) Int
n
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
255 = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
0 Word64
0 Word64
0 Word64
0
    | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0           = Word256
w
    | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
64          = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
0 Word64
a3 Word64
a2 Word64
a1
    | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
128         = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
0 Word64
0 Word64
a3 Word64
a2
    | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
192         = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
0 Word64
0 Word64
0 Word64
a3
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<  Int
64          = Word64 -> Word64 -> Word64 -> Word64 -> Int -> Word256
mkWordShift Word64
a3 Word64
a2 Word64
a1 Word64
a0 Int
n
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
128          = Word64 -> Word64 -> Word64 -> Word64 -> Int -> Word256
mkWordShift  Word64
0 Word64
a3 Word64
a2 Word64
a1 (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
64)
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
192          = Word64 -> Word64 -> Word64 -> Word64 -> Int -> Word256
mkWordShift  Word64
0  Word64
0 Word64
a3 Word64
a2 (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
128)
    | Bool
otherwise        = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
0 Word64
0 Word64
0 (Word64
a3 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftR` (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
192))
  where
    mkWordShift :: Word64 -> Word64 -> Word64 -> Word64 -> Int -> Word256
    mkWordShift :: Word64 -> Word64 -> Word64 -> Word64 -> Int -> Word256
mkWordShift Word64
w Word64
x Word64
y Word64
z Int
s =
        Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 (Word64
w Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftR` Int
s) (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
w Int
s' Word64
x Int
s) (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
x Int
s' Word64
y Int
s) (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
y Int
s' Word64
z Int
s)
      where s' :: Int
s' = Int -> Int
inv64 Int
s

-- | Bitwise rotate Left
rotateL :: Word256 -> Int -> Word256
rotateL :: Word256 -> Int -> Word256
rotateL (Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0) Int
n'
    | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0    = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0
    | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
192  = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
a0 Word64
a3 Word64
a2 Word64
a1
    | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
128  = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
a1 Word64
a0 Word64
a3 Word64
a2
    | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
64   = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
a2 Word64
a1 Word64
a0 Word64
a3
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
64    = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a3 Int
n Word64
a2 (Int -> Int
inv64 Int
n)) (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a2 Int
n Word64
a1 (Int -> Int
inv64 Int
n))
                          (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a1 Int
n Word64
a0 (Int -> Int
inv64 Int
n)) (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a0 Int
n Word64
a3 (Int -> Int
inv64 Int
n))
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
128   = let n :: Int
n = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
64 in Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256
                          (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a2 Int
n Word64
a1 (Int -> Int
inv64 Int
n)) (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a1 Int
n Word64
a0 (Int -> Int
inv64 Int
n))
                          (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a0 Int
n Word64
a3 (Int -> Int
inv64 Int
n)) (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a3 Int
n Word64
a2 (Int -> Int
inv64 Int
n))
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
192   = let n :: Int
n = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
128 in Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256
                          (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a1 Int
n Word64
a0 (Int -> Int
inv64 Int
n)) (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a0 Int
n Word64
a3 (Int -> Int
inv64 Int
n))
                          (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a3 Int
n Word64
a2 (Int -> Int
inv64 Int
n)) (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a2 Int
n Word64
a1 (Int -> Int
inv64 Int
n))
    | Bool
otherwise = let n :: Int
n = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
192 in Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256
                          (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a0 Int
n Word64
a3 (Int -> Int
inv64 Int
n)) (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a3 Int
n Word64
a2 (Int -> Int
inv64 Int
n))
                          (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a2 Int
n Word64
a1 (Int -> Int
inv64 Int
n)) (Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
a1 Int
n Word64
a0 (Int -> Int
inv64 Int
n))
  where
    n :: Int
    n :: Int
n | Int
n' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0   = Int
n' Int -> Int -> Int
forall a. Integral a => a -> a -> a
`Prelude.mod` Int
256
      | Bool
otherwise = Int
256 Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- (Int
n' Int -> Int -> Int
forall a. Integral a => a -> a -> a
`Prelude.mod` Int
256)

-- | Bitwise rotate Left
rotateR :: Word256 -> Int -> Word256
rotateR :: Word256 -> Int -> Word256
rotateR Word256
w Int
n = Word256 -> Int -> Word256
rotateL Word256
w (Int
256 Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
n)

inv64 :: Int -> Int
inv64 :: Int -> Int
inv64 Int
i = Int
64 Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
i

comb64 :: Word64 -> Int -> Word64 -> Int -> Word64
comb64 :: Word64 -> Int -> Word64 -> Int -> Word64
comb64 Word64
x Int
i Word64
y Int
j =
    (Word64
x Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftL` Int
i) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word64
y Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftR` Int
j)

-- | Test bit
testBit :: Word256 -> Int -> Bool
testBit :: Word256 -> Int -> Bool
testBit (Word256 Word64
a3 Word64
a2 Word64
a1 Word64
a0) Int
n
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
255 = Bool
False
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
191          = Word64 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
Bits.testBit Word64
a3 (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
192)
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
127          = Word64 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
Bits.testBit Word64
a2 (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
128)
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
63           = Word64 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
Bits.testBit Word64
a1 (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
64)
    | Bool
otherwise        = Word64 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
Bits.testBit Word64
a0 Int
n

-- | bit
bit :: Int -> Word256
bit :: Int -> Word256
bit Int
n
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
255 = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
0 Word64
0 Word64
0 Word64
0
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
191          = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 (Int -> Word64
forall a. Bits a => Int -> a
Bits.bit (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
192)) Word64
0 Word64
0 Word64
0
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
127          = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
0 (Int -> Word64
forall a. Bits a => Int -> a
Bits.bit (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
128)) Word64
0 Word64
0
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
63           = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
0 Word64
0 (Int -> Word64
forall a. Bits a => Int -> a
Bits.bit (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
Prelude.- Int
64)) Word64
0
    | Bool
otherwise        = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256 Word64
0 Word64
0 Word64
0 (Int -> Word64
forall a. Bits a => Int -> a
Bits.bit Int
n)

literal :: Integer -> Word256
literal :: Integer -> Word256
literal Integer
i = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256
    (Integer -> Word64
forall a. Num a => Integer -> a
Prelude.fromInteger (Integer
i Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftR` Int
192))
    (Integer -> Word64
forall a. Num a => Integer -> a
Prelude.fromInteger (Integer
i Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftR` Int
128))
    (Integer -> Word64
forall a. Num a => Integer -> a
Prelude.fromInteger (Integer
i Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftR` Int
64))
    (Integer -> Word64
forall a. Num a => Integer -> a
Prelude.fromInteger Integer
i)

fromNatural :: Natural -> Word256
fromNatural :: Natural -> Word256
fromNatural Natural
n = Word64 -> Word64 -> Word64 -> Word64 -> Word256
Word256
    (Integer -> Word64
forall a. Num a => Integer -> a
Prelude.fromInteger (Natural -> Integer
naturalToInteger Natural
n Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftR` Int
192))
    (Integer -> Word64
forall a. Num a => Integer -> a
Prelude.fromInteger (Natural -> Integer
naturalToInteger Natural
n Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftR` Int
128))
    (Integer -> Word64
forall a. Num a => Integer -> a
Prelude.fromInteger (Natural -> Integer
naturalToInteger Natural
n Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`Bits.unsafeShiftR` Int
64))
    (Integer -> Word64
forall a. Num a => Integer -> a
Prelude.fromInteger (Integer -> Word64) -> Integer -> Word64
forall a b. (a -> b) -> a -> b
$ Natural -> Integer
naturalToInteger Natural
n)