{-# language CPP #-}
{-# language DataKinds #-}
{-# language MagicHash #-}
{-# language TypeApplications #-}
{-# language UnboxedTuples #-}
{-# language ViewPatterns #-}

#include <MachDeps.h>

module Basics.Word128
  ( -- Types
    T
  , T#
  , R
    -- Lifting
  , lift
  , unlift
    -- Compare
  , eq#
  , neq#
  , lt#
  , lte#
  , gt#
  , gt
  , gte
  , lt
  , lte
  , eq
  , neq
    -- Arithmetic
  , minus#
  , quot#
    -- Array
  , read#
  , write#
  , index#
  , read
  , write
  , index
  , set#
  , uninitialized#
  , initialized#
  , uninitialized
  , initialized
  , copy#
  , copyMutable#
  , shrink#
  , shrink
    -- Constants
  , def
  , zero
  , minBound
  , maxBound
    -- Metadata
  , size
    -- Encoding
  , shows
  ) where

import Prelude hiding (shows,minBound,maxBound,read)

import Data.Primitive (MutableByteArray(..),ByteArray(..))
import Data.WideWord.Word128 (Word128(Word128))
import GHC.Exts hiding (setByteArray#)
import GHC.ST (ST(ST))
import GHC.Word (Word64(W64#))

import qualified Prelude
import qualified GHC.Exts as Exts

type T = Word128
type T# = (# Word#, Word# #)
type R = 'TupleRep '[ 'WordRep, 'WordRep ]

def :: T
{-# inline def #-}
def :: T
def = T
0

zero :: T
{-# inline zero #-}
zero :: T
zero = T
0

maxBound :: T
{-# inline maxBound #-}
maxBound :: T
maxBound = Word64 -> Word64 -> T
Word128 Word64
18446744073709551615 Word64
18446744073709551615

minBound :: T
{-# inline minBound #-}
minBound :: T
minBound = T
0

size :: Int
{-# inline size #-}
size :: Int
size = Int
16

lt# :: T# -> T# -> Int#
{-# inline lt# #-}
lt# :: T# -> T# -> Int#
lt# (# Word#
a1, Word#
a2 #) (# Word#
b1, Word#
b2 #) = case Word# -> Word# -> Int#
ltWord# Word#
a1 Word#
b1 of
  Int#
1# -> Int#
1#
  Int#
_ -> case Word# -> Word# -> Int#
eqWord# Word#
a1 Word#
b1 of
    Int#
1# -> Word# -> Word# -> Int#
ltWord# Word#
a2 Word#
b2
    Int#
_ -> Int#
0#

gt# :: T# -> T# -> Int#
{-# inline gt# #-}
gt# :: T# -> T# -> Int#
gt# (# Word#
a1, Word#
a2 #) (# Word#
b1, Word#
b2 #) = case Word# -> Word# -> Int#
gtWord# Word#
a1 Word#
b1 of
  Int#
1# -> Int#
1#
  Int#
_ -> case Word# -> Word# -> Int#
eqWord# Word#
a1 Word#
b1 of
    Int#
1# -> Word# -> Word# -> Int#
gtWord# Word#
a2 Word#
b2
    Int#
_ -> Int#
0#

gt :: T -> T -> Bool
{-# inline gt #-}
gt :: T -> T -> Bool
gt = forall a. Ord a => a -> a -> Bool
(>)

lt :: T -> T -> Bool
{-# inline lt #-}
lt :: T -> T -> Bool
lt = forall a. Ord a => a -> a -> Bool
(<)

gte :: T -> T -> Bool
{-# inline gte #-}
gte :: T -> T -> Bool
gte = forall a. Ord a => a -> a -> Bool
(>=)

lte :: T -> T -> Bool
{-# inline lte #-}
lte :: T -> T -> Bool
lte = forall a. Ord a => a -> a -> Bool
(<=)

lte# :: T# -> T# -> Int#
{-# inline lte# #-}
lte# :: T# -> T# -> Int#
lte# (# Word#
a1, Word#
a2 #) (# Word#
b1, Word#
b2 #) = case Word# -> Word# -> Int#
ltWord# Word#
a1 Word#
a2 of
  Int#
1# -> Int#
1#
  Int#
_ -> case Word# -> Word# -> Int#
eqWord# Word#
a1 Word#
b1 of
    Int#
1# -> Word# -> Word# -> Int#
leWord# Word#
a2 Word#
b2
    Int#
_ -> Int#
0#

quot# :: T# -> T# -> T#
{-# inline quot# #-}
quot# :: T# -> T# -> T#
quot# (# Word#
a1, Word#
a2 #) (# Word#
b1, Word#
b2 #) =
  case forall a. Integral a => a -> a -> a
quot (Word64 -> Word64 -> T
Word128 (Word# -> Word64
W64# Word#
a1) (Word# -> Word64
W64# Word#
a2)) (Word64 -> Word64 -> T
Word128 (Word# -> Word64
W64# Word#
b1) (Word# -> Word64
W64# Word#
b2)) of
    Word128 (W64# Word#
c1) (W64# Word#
c2) -> (# Word#
c1, Word#
c2 #)

minus# :: T# -> T# -> T#
{-# inline minus# #-}
minus# :: T# -> T# -> T#
minus# (# Word#
a1, Word#
a2 #) (# Word#
b1, Word#
b2 #) =
  case (Word64 -> Word64 -> T
Word128 (Word# -> Word64
W64# Word#
a1) (Word# -> Word64
W64# Word#
a2)) forall a. Num a => a -> a -> a
- (Word64 -> Word64 -> T
Word128 (Word# -> Word64
W64# Word#
b1) (Word# -> Word64
W64# Word#
b2)) of
    Word128 (W64# Word#
c1) (W64# Word#
c2) -> (# Word#
c1, Word#
c2 #)

lift :: T# -> T
{-# inline lift #-}
lift :: T# -> T
lift (# Word#
a, Word#
b #) = Word64 -> Word64 -> T
Word128 (Word# -> Word64
W64# Word#
a) (Word# -> Word64
W64# Word#
b)

unlift :: T -> T#
{-# inline unlift #-}
unlift :: T -> T#
unlift (Word128 (W64# Word#
a) (W64# Word#
b)) = (# Word#
a, Word#
b #)

eq# :: T# -> T# -> Int#
{-# inline eq# #-}
eq# :: T# -> T# -> Int#
eq# (# Word#
x1, Word#
y1 #) (# Word#
x2, Word#
y2 #) = ((Word# -> Word# -> Int#
eqWord# Word#
x1 Word#
x2) Int# -> Int# -> Int#
`andI#` (Word# -> Word# -> Int#
eqWord# Word#
y1 Word#
y2))

neq# :: T# -> T# -> Int#
{-# inline neq# #-}
neq# :: T# -> T# -> Int#
neq# (# Word#
x1, Word#
y1 #) (# Word#
x2, Word#
y2 #) = ((Word# -> Word# -> Int#
neWord# Word#
x1 Word#
x2) Int# -> Int# -> Int#
`orI#` (Word# -> Word# -> Int#
neWord# Word#
y1 Word#
y2))

eq :: T -> T -> Bool
{-# inline eq #-}
eq :: T -> T -> Bool
eq = forall a. Eq a => a -> a -> Bool
(==)

neq :: T -> T -> Bool
{-# inline neq #-}
neq :: T -> T -> Bool
neq = forall a. Eq a => a -> a -> Bool
(/=)

index :: ByteArray -> Int -> T
{-# inline index #-}
index :: ByteArray -> Int -> T
index (ByteArray ByteArray#
x) (I# Int#
i) = T# -> T
lift (ByteArray# -> Int# -> T#
index# ByteArray#
x Int#
i)

read :: MutableByteArray s -> Int -> ST s T
{-# inline read #-}
read :: forall s. MutableByteArray s -> Int -> ST s T
read (MutableByteArray MutableByteArray# s
x) (I# Int#
i) = forall s a. STRep s a -> ST s a
ST
  (\State# s
s0 -> case forall s.
MutableByteArray# s -> Int# -> State# s -> (# State# s, T# #)
read# MutableByteArray# s
x Int#
i State# s
s0 of
    (# State# s
s1, T#
r #) -> (# State# s
s1, T# -> T
lift T#
r #)
  )

write :: MutableByteArray s -> Int -> T -> ST s ()
{-# inline write #-}
write :: forall s. MutableByteArray s -> Int -> T -> ST s ()
write (MutableByteArray MutableByteArray# s
x) (I# Int#
i) (T -> T#
unlift -> T#
e) = forall s a. STRep s a -> ST s a
ST (\State# s
s -> (# forall s. MutableByteArray# s -> Int# -> T# -> State# s -> State# s
write# MutableByteArray# s
x Int#
i T#
e State# s
s, () #) )

set# :: MutableByteArray# s -> Int# -> Int# -> T# -> State# s -> State# s
{-# inline set# #-}
set# :: forall s.
MutableByteArray# s -> Int# -> Int# -> T# -> State# s -> State# s
set# MutableByteArray# s
marr Int#
off Int#
len T#
x State# s
s = case Int#
len of
  Int#
0# -> State# s
s
  Int#
_ -> forall s.
MutableByteArray# s -> Int# -> Int# -> T# -> State# s -> State# s
set# MutableByteArray# s
marr (Int#
off Int# -> Int# -> Int#
+# Int#
1# ) (Int#
len Int# -> Int# -> Int#
-# Int#
1# ) T#
x (forall s. MutableByteArray# s -> Int# -> T# -> State# s -> State# s
write# MutableByteArray# s
marr Int#
off T#
x State# s
s)

uninitialized# :: Int# -> State# s -> (# State# s, MutableByteArray# s #)
{-# inline uninitialized# #-}
uninitialized# :: forall s. Int# -> State# s -> (# State# s, MutableByteArray# s #)
uninitialized# Int#
sz = forall s. Int# -> State# s -> (# State# s, MutableByteArray# s #)
Exts.newByteArray# (Int#
sz Int# -> Int# -> Int#
*# Int#
16# )

initialized# ::
     Int# -> T# -> State# s
  -> (# State# s, MutableByteArray# s #)
{-# inline initialized# #-}
initialized# :: forall s.
Int# -> T# -> State# s -> (# State# s, MutableByteArray# s #)
initialized# Int#
n T#
e State# s
s0 = case forall s. Int# -> State# s -> (# State# s, MutableByteArray# s #)
uninitialized# Int#
n State# s
s0 of
  (# State# s
s1, MutableByteArray# s
a #) -> case forall s.
MutableByteArray# s -> Int# -> Int# -> T# -> State# s -> State# s
set# MutableByteArray# s
a Int#
0# Int#
n T#
e State# s
s1 of
    State# s
s2 -> (# State# s
s2, MutableByteArray# s
a #)

uninitialized :: Int -> ST s (MutableByteArray s)
{-# inline uninitialized #-}
uninitialized :: forall s. Int -> ST s (MutableByteArray s)
uninitialized (I# Int#
sz) = forall s a. STRep s a -> ST s a
ST forall a b. (a -> b) -> a -> b
$ \State# s
s0 -> case forall s. Int# -> State# s -> (# State# s, MutableByteArray# s #)
uninitialized# Int#
sz State# s
s0 of
  (# State# s
s1, MutableByteArray# s
a #) -> (# State# s
s1, forall s. MutableByteArray# s -> MutableByteArray s
MutableByteArray MutableByteArray# s
a #)

initialized :: Int -> T -> ST s (MutableByteArray s)
{-# inline initialized #-}
initialized :: forall s. Int -> T -> ST s (MutableByteArray s)
initialized (I# Int#
sz) T
e = forall s a. STRep s a -> ST s a
ST forall a b. (a -> b) -> a -> b
$ \State# s
s0 -> case forall s.
Int# -> T# -> State# s -> (# State# s, MutableByteArray# s #)
initialized# Int#
sz (T -> T#
unlift T
e) State# s
s0 of
  (# State# s
s1, MutableByteArray# s
a #) -> (# State# s
s1, forall s. MutableByteArray# s -> MutableByteArray s
MutableByteArray MutableByteArray# s
a #)

copy# :: MutableByteArray# s -> Int# -> ByteArray# -> Int# -> Int# -> State# s -> State# s
{-# inline copy# #-}
copy# :: forall s.
MutableByteArray# s
-> Int# -> ByteArray# -> Int# -> Int# -> State# s -> State# s
copy# MutableByteArray# s
dst Int#
doff ByteArray#
src Int#
soff Int#
len =
  forall d.
ByteArray#
-> Int#
-> MutableByteArray# d
-> Int#
-> Int#
-> State# d
-> State# d
Exts.copyByteArray# ByteArray#
src (Int#
soff Int# -> Int# -> Int#
*# Int#
16#) MutableByteArray# s
dst (Int#
doff Int# -> Int# -> Int#
*# Int#
16#) (Int#
len Int# -> Int# -> Int#
*# Int#
16#)

copyMutable# :: MutableByteArray# s -> Int# -> MutableByteArray# s -> Int# -> Int# -> State# s -> State# s
{-# inline copyMutable# #-}
copyMutable# :: forall s.
MutableByteArray# s
-> Int#
-> MutableByteArray# s
-> Int#
-> Int#
-> State# s
-> State# s
copyMutable# MutableByteArray# s
dst Int#
doff MutableByteArray# s
src Int#
soff Int#
len =
  forall s.
MutableByteArray# s
-> Int#
-> MutableByteArray# s
-> Int#
-> Int#
-> State# s
-> State# s
Exts.copyMutableByteArray# MutableByteArray# s
src (Int#
soff Int# -> Int# -> Int#
*# Int#
16#) MutableByteArray# s
dst (Int#
doff Int# -> Int# -> Int#
*# Int#
16#) (Int#
len Int# -> Int# -> Int#
*# Int#
16#)

shrink# :: MutableByteArray# s -> Int# -> State# s -> (# State# s, MutableByteArray# s #)
{-# inline shrink# #-}
shrink# :: forall s.
MutableByteArray# s
-> Int# -> State# s -> (# State# s, MutableByteArray# s #)
shrink# MutableByteArray# s
m Int#
i State# s
s0 = (# forall d. MutableByteArray# d -> Int# -> State# d -> State# d
Exts.shrinkMutableByteArray# MutableByteArray# s
m (Int#
i Int# -> Int# -> Int#
*# Int#
16#) State# s
s0, MutableByteArray# s
m #)

shrink :: MutableByteArray s -> Int -> ST s (MutableByteArray s)
{-# inline shrink #-}
shrink :: forall s. MutableByteArray s -> Int -> ST s (MutableByteArray s)
shrink (MutableByteArray MutableByteArray# s
x) (I# Int#
i) = forall s a. STRep s a -> ST s a
ST
  (\State# s
s0 -> case forall s.
MutableByteArray# s
-> Int# -> State# s -> (# State# s, MutableByteArray# s #)
shrink# MutableByteArray# s
x Int#
i State# s
s0 of
    (# State# s
s1, MutableByteArray# s
r #) -> (# State# s
s1, forall s. MutableByteArray# s -> MutableByteArray s
MutableByteArray MutableByteArray# s
r #)
  )

shows :: T -> String -> String
shows :: T -> String -> String
shows = forall a. Show a => a -> String -> String
Prelude.shows

#if WORDS_BIGENDIAN
index# :: ByteArray# -> Int# -> T#
{-# inline index# #-}
index# arr# i# =
  (# Exts.indexWordArray# arr# (2# *# i#)
  ,  Exts.indexWordArray# arr# ((2# *# i#) +# 1#) #)

read# :: MutableByteArray# s -> Int# -> State# s -> (# State# s, T# #)
{-# inline read# #-}
read# arr# i# s0 = case Exts.readWordArray# arr# (2# *# i#) s0 of
  (# s1, i0 #) -> case Exts.readWordArray# arr# ((2# *# i#) +# 1#) s1 of
    (# s2, i1 #) -> (# s2, (# i0, i1 #) #)

write# :: MutableByteArray# s -> Int# -> T# -> State# s -> State# s
{-# inline write# #-}
write# arr# i# (# a, b #) s0 =
  case Exts.writeWordArray# arr# (2# *# i#) a s0 of
    s1 -> case Exts.writeWordArray# arr# ((2# *# i#) +# 1#) b s1 of
      s2 -> s2
#else
index# :: ByteArray# -> Int# -> T#
{-# inline index# #-}
index# :: ByteArray# -> Int# -> T#
index# ByteArray#
arr# Int#
i# =
  (# ByteArray# -> Int# -> Word#
Exts.indexWordArray# ByteArray#
arr# ((Int#
2# Int# -> Int# -> Int#
*# Int#
i#) Int# -> Int# -> Int#
+# Int#
1#)
  ,  ByteArray# -> Int# -> Word#
Exts.indexWordArray# ByteArray#
arr# (Int#
2# Int# -> Int# -> Int#
*# Int#
i#) #)

read# :: MutableByteArray# s -> Int# -> State# s -> (# State# s, T# #)
{-# inline read# #-}
read# :: forall s.
MutableByteArray# s -> Int# -> State# s -> (# State# s, T# #)
read# MutableByteArray# s
arr# Int#
i# State# s
s0 = case forall d.
MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
Exts.readWordArray# MutableByteArray# s
arr# ((Int#
2# Int# -> Int# -> Int#
*# Int#
i#) Int# -> Int# -> Int#
+# Int#
1#) State# s
s0 of
  (# State# s
s1, Word#
i0 #) -> case forall d.
MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
Exts.readWordArray# MutableByteArray# s
arr# (Int#
2# Int# -> Int# -> Int#
*# Int#
i#) State# s
s1 of
    (# State# s
s2, Word#
i1 #) -> (# State# s
s2, (# Word#
i0, Word#
i1 #) #)

write# :: MutableByteArray# s -> Int# -> T# -> State# s -> State# s
{-# inline write# #-}
write# :: forall s. MutableByteArray# s -> Int# -> T# -> State# s -> State# s
write# MutableByteArray# s
arr# Int#
i# (# Word#
a, Word#
b #) State# s
s0 =
  case forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
Exts.writeWordArray# MutableByteArray# s
arr# ((Int#
2# Int# -> Int# -> Int#
*# Int#
i#) Int# -> Int# -> Int#
+# Int#
1#) Word#
a State# s
s0 of
    State# s
s1 -> case forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
Exts.writeWordArray# MutableByteArray# s
arr# (Int#
2# Int# -> Int# -> Int#
*# Int#
i#) Word#
b State# s
s1 of
      State# s
s2 -> State# s
s2
#endif