{-# language CPP #-}
{-# language BangPatterns #-}
{-# language MagicHash #-}
{-# language RankNTypes #-}
{-# language TypeApplications #-}
{-# language TypeFamilies #-}
{-# language TypeInType #-}
{-# language StandaloneKindSignatures #-}
{-# language UnboxedTuples #-}

module Word128
  ( R
  , A#
  , M#
  , empty#
  , index#
  , write#
  , read#
  , unsafeFreeze#
  , initialized#
  , set#
  , unsafeShrinkFreeze#
  , thaw#
  , freeze#
  , copy#
  ) where

import GHC.Exts
import Data.Kind (Type)
import Data.Unlifted (PrimArray#(..),MutablePrimArray#(..))
import EmptyPrimArray (emptyPrimArray#)

import qualified GHC.Exts as Exts

type A# = PrimArray# @( 'TupleRep '[ 'Word64Rep, 'Word64Rep ] )
type M# = MutablePrimArray# @( 'TupleRep '[ 'Word64Rep, 'Word64Rep ] )
type R = ( 'TupleRep '[ 'Word64Rep, 'Word64Rep ] )

unsafeFromW128 :: forall (a :: TYPE ( 'TupleRep '[ 'Word64Rep, 'Word64Rep ] )). (# Word64#, Word64# #) -> a
{-# inline unsafeFromW128 #-}
unsafeFromW128 :: forall (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
(# Word64#, Word64# #) -> a
unsafeFromW128 (# Word64#
x, Word64#
y #) = (# Word64#, Word64# #) -> a
forall a b. a -> b
unsafeCoerce# (# Word64#
x, Word64#
y #)

unsafeToW128 :: forall (a :: TYPE ( 'TupleRep '[ 'Word64Rep, 'Word64Rep ] )). a -> (# Word64#, Word64# #)
{-# inline unsafeToW128 #-}
unsafeToW128 :: forall (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
a -> (# Word64#, Word64# #)
unsafeToW128 a
x = a -> (# Word64#, Word64# #)
forall a b. a -> b
unsafeCoerce# a
x

empty# :: forall (a :: TYPE R). (# #) -> A# a
empty# :: forall (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
(# #) -> A# a
empty# = (# #) -> PrimArray# a
forall a. (# #) -> PrimArray# a
emptyPrimArray#

thaw# :: forall (s :: Type) (a :: TYPE R).
     A# a
  -> Int#
  -> Int#
  -> State# s
  -> (# State# s, M# s a #)
thaw# :: forall s (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
A# a -> Int# -> Int# -> State# s -> (# State# s, M# s a #)
thaw# (PrimArray# ByteArray#
v) Int#
off Int#
len State# s
s0 = case Int# -> State# s -> (# State# s, MutableByteArray# s #)
forall d. Int# -> State# d -> (# State# d, MutableByteArray# d #)
Exts.newByteArray# (Int#
len Int# -> Int# -> Int#
*# Int#
16# ) State# s
s0 of
  (# State# s
s1, MutableByteArray# s
m #) -> case ByteArray#
-> Int#
-> MutableByteArray# s
-> Int#
-> Int#
-> State# s
-> State# s
forall d.
ByteArray#
-> Int#
-> MutableByteArray# d
-> Int#
-> Int#
-> State# d
-> State# d
Exts.copyByteArray# ByteArray#
v (Int#
off Int# -> Int# -> Int#
*# Int#
16# ) MutableByteArray# s
m Int#
0# (Int#
len Int# -> Int# -> Int#
*# Int#
16# ) State# s
s1 of
    State# s
s2 -> (# State# s
s2, MutableByteArray# s -> M# s a
forall a b. MutableByteArray# a -> MutablePrimArray# a b
MutablePrimArray# MutableByteArray# s
m #)

freeze# :: forall (s :: Type) (a :: TYPE R).
     M# s a
  -> Int#
  -> Int#
  -> State# s
  -> (# State# s, A# a #)
freeze# :: forall s (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
M# s a -> Int# -> Int# -> State# s -> (# State# s, A# a #)
freeze# (MutablePrimArray# MutableByteArray# s
v) Int#
off Int#
len State# s
s0 = case Int# -> State# s -> (# State# s, MutableByteArray# s #)
forall d. Int# -> State# d -> (# State# d, MutableByteArray# d #)
Exts.newByteArray# (Int#
len Int# -> Int# -> Int#
*# Int#
16# ) State# s
s0 of
  (# State# s
s1, MutableByteArray# s
m #) -> case MutableByteArray# s
-> Int#
-> MutableByteArray# s
-> Int#
-> Int#
-> State# s
-> State# s
forall d.
MutableByteArray# d
-> Int#
-> MutableByteArray# d
-> Int#
-> Int#
-> State# d
-> State# d
Exts.copyMutableByteArray# MutableByteArray# s
v (Int#
off Int# -> Int# -> Int#
*# Int#
16# ) MutableByteArray# s
m Int#
0# (Int#
len Int# -> Int# -> Int#
*# Int#
16# ) State# s
s1 of
    State# s
s2 -> case MutableByteArray# s -> State# s -> (# State# s, ByteArray# #)
forall d.
MutableByteArray# d -> State# d -> (# State# d, ByteArray# #)
Exts.unsafeFreezeByteArray# MutableByteArray# s
m State# s
s2 of
      (# State# s
s3, ByteArray#
x #) -> (# State# s
s3, ByteArray# -> A# a
forall a. ByteArray# -> PrimArray# a
PrimArray# ByteArray#
x #)

-- shrink and freeze, all at once
unsafeShrinkFreeze# ::
     M# s a
  -> Int# -- number of elements to preserve
  -> State# s
  -> (# State# s, A# a #)
unsafeShrinkFreeze# :: forall s (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
M# s a -> Int# -> State# s -> (# State# s, A# a #)
unsafeShrinkFreeze# (MutablePrimArray# MutableByteArray# s
m) Int#
elemCount State# s
s0Alpha =
  let !byteCount :: Int#
byteCount = Int#
elemCount Int# -> Int# -> Int#
*# Int#
16#
   in case MutableByteArray# s -> State# s -> (# State# s, Int# #)
forall d. MutableByteArray# d -> State# d -> (# State# d, Int# #)
getSizeofMutableByteArray# MutableByteArray# s
m State# s
s0Alpha of
        (# State# s
s0, Int#
sz #) -> case Int#
sz Int# -> Int# -> Int#
==# Int#
byteCount of
          Int#
1# -> case MutableByteArray# s -> State# s -> (# State# s, ByteArray# #)
forall d.
MutableByteArray# d -> State# d -> (# State# d, ByteArray# #)
Exts.unsafeFreezeByteArray# MutableByteArray# s
m State# s
s0 of
            (# State# s
s1, ByteArray#
v #) -> (# State# s
s1, ByteArray# -> A# a
forall a. ByteArray# -> PrimArray# a
PrimArray# ByteArray#
v #)
          Int#
_ -> case MutableByteArray# s -> Int# -> State# s -> State# s
forall d. MutableByteArray# d -> Int# -> State# d -> State# d
Exts.shrinkMutableByteArray# MutableByteArray# s
m Int#
byteCount State# s
s0 of
            State# s
s1 -> case MutableByteArray# s -> State# s -> (# State# s, ByteArray# #)
forall d.
MutableByteArray# d -> State# d -> (# State# d, ByteArray# #)
Exts.unsafeFreezeByteArray# MutableByteArray# s
m State# s
s1 of
              (# State# s
s2, ByteArray#
v #) -> (# State# s
s2, ByteArray# -> A# a
forall a. ByteArray# -> PrimArray# a
PrimArray# ByteArray#
v #)

unsafeFreeze# :: forall (s :: Type) (a :: TYPE R).
     M# s a
  -> State# s
  -> (# State# s, A# a #)
unsafeFreeze# :: forall s (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
M# s a -> State# s -> (# State# s, A# a #)
unsafeFreeze# (MutablePrimArray# MutableByteArray# s
m) State# s
s0 = case MutableByteArray# s -> State# s -> (# State# s, ByteArray# #)
forall d.
MutableByteArray# d -> State# d -> (# State# d, ByteArray# #)
unsafeFreezeByteArray# MutableByteArray# s
m State# s
s0 of
  (# State# s
s1, ByteArray#
v #) -> (# State# s
s1, ByteArray# -> A# a
forall a. ByteArray# -> PrimArray# a
PrimArray# ByteArray#
v #)

copy# :: M# s a -> Int# -> A# a -> Int# -> Int# -> State# s -> State# s
{-# inline copy# #-}
copy# :: forall s (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
M# s a -> Int# -> A# a -> Int# -> Int# -> State# s -> State# s
copy# (MutablePrimArray# MutableByteArray# s
dst) Int#
doff (PrimArray# ByteArray#
src) Int#
soff Int#
len =
  ByteArray#
-> Int#
-> MutableByteArray# s
-> Int#
-> Int#
-> State# s
-> State# s
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#)

-- Not exported. Offset and length are counts of elements, not bytes
setLoop# :: forall (s :: Type) (a :: TYPE R). M# s a -> Int# -> Int# -> a -> State# s -> State# s
setLoop# :: forall s (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
M# s a -> Int# -> Int# -> a -> State# s -> State# s
setLoop# M# s a
marr Int#
off Int#
len a
x State# s
s = case Int#
len of                                    
  Int#
0# -> State# s
s
  Int#
_ -> M# s a -> Int# -> Int# -> a -> State# s -> State# s
forall s (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
M# s a -> Int# -> Int# -> a -> State# s -> State# s
setLoop# M# s a
marr (Int#
off Int# -> Int# -> Int#
+# Int#
1# ) (Int#
len Int# -> Int# -> Int#
-# Int#
1# ) a
x (M# s a -> Int# -> a -> State# s -> State# s
forall s (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
M# s a -> Int# -> a -> State# s -> State# s
write# M# s a
marr Int#
off a
x State# s
s)                         

set# :: forall (s :: Type) (a :: TYPE R).
     M# s a
  -> Int#
  -> Int#
  -> a
  -> State# s
  -> State# s
set# :: forall s (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
M# s a -> Int# -> Int# -> a -> State# s -> State# s
set# m :: M# s a
m@(MutablePrimArray# MutableByteArray# s
b) Int#
off0 Int#
len0 a
a State# s
s0 = case a -> (# Word64#, Word64# #)
forall (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
a -> (# Word64#, Word64# #)
unsafeToW128 a
a of
  (# Word64#
x, Word64#
y #) | Word#
0## <- Word64# -> Word#
Exts.word64ToWord# Word64#
x, Word#
0## <- Word64# -> Word#
Exts.word64ToWord# Word64#
y -> MutableByteArray# s -> Int# -> Int# -> Int# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Int# -> Int# -> State# d -> State# d
Exts.setByteArray# MutableByteArray# s
b (Int#
off0 Int# -> Int# -> Int#
*# Int#
16# ) (Int#
len0 Int# -> Int# -> Int#
*# Int#
16# ) Int#
0# State# s
s0
  (# Word64#, Word64# #)
_ -> M# s a -> Int# -> Int# -> a -> State# s -> State# s
forall s (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
M# s a -> Int# -> Int# -> a -> State# s -> State# s
setLoop# M# s a
m Int#
off0 Int#
len0 a
a State# s
s0


initialized# :: forall (s :: Type) (a :: TYPE R).
     Int#
  -> a
  -> State# s
  -> (# State# s, M# s a #)
initialized# :: forall s (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
Int# -> a -> State# s -> (# State# s, M# s a #)
initialized# Int#
n a
a State# s
s0 = case Int# -> State# s -> (# State# s, MutableByteArray# s #)
forall d. Int# -> State# d -> (# State# d, MutableByteArray# d #)
newByteArray# (Int#
n Int# -> Int# -> Int#
*# Int#
16# ) State# s
s0 of
  (# State# s
s1, MutableByteArray# s
b #) -> case a -> (# Word64#, Word64# #)
forall (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
a -> (# Word64#, Word64# #)
unsafeToW128 a
a of
    (# Word64#
x, Word64#
y #) | Word#
0## <- Word64# -> Word#
Exts.word64ToWord# Word64#
x, Word#
0## <- Word64# -> Word#
Exts.word64ToWord# Word64#
y -> case MutableByteArray# s -> Int# -> Int# -> Int# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Int# -> Int# -> State# d -> State# d
Exts.setByteArray# MutableByteArray# s
b Int#
0# (Int#
n Int# -> Int# -> Int#
*# Int#
16#) Int#
0# State# s
s1 of
      State# s
s2 -> (# State# s
s2, MutableByteArray# s -> M# s a
forall a b. MutableByteArray# a -> MutablePrimArray# a b
MutablePrimArray# MutableByteArray# s
b #)
    (# Word64#, Word64# #)
_ -> case M# s a -> Int# -> Int# -> a -> State# s -> State# s
forall s (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
M# s a -> Int# -> Int# -> a -> State# s -> State# s
setLoop# (MutableByteArray# s -> M# s a
forall a b. MutableByteArray# a -> MutablePrimArray# a b
MutablePrimArray# MutableByteArray# s
b) Int#
0# Int#
n a
a State# s
s1 of
      State# s
s2 -> (# State# s
s2, MutableByteArray# s -> M# s a
forall a b. MutableByteArray# a -> MutablePrimArray# a b
MutablePrimArray# MutableByteArray# s
b #)

#if WORDS_BIGENDIAN

-- TODO: Handle big-endian arch if I ever need to.

#else
index# :: forall (a :: TYPE R). A# a -> Int# -> a
{-# inline index# #-}
index# :: forall (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
A# a -> Int# -> a
index# (PrimArray# ByteArray#
arr#) Int#
i# = (# Word64#, Word64# #) -> a
forall (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
(# Word64#, Word64# #) -> a
unsafeFromW128
  (# ByteArray# -> Int# -> Word64#
Exts.indexWord64Array# ByteArray#
arr# ((Int#
2# Int# -> Int# -> Int#
*# Int#
i#) Int# -> Int# -> Int#
+# Int#
1#)
  ,  ByteArray# -> Int# -> Word64#
Exts.indexWord64Array# ByteArray#
arr# (Int#
2# Int# -> Int# -> Int#
*# Int#
i#) #)

read# :: forall (s :: Type) (a :: TYPE R). M# s a -> Int# -> State# s -> (# State# s, a #)
{-# inline read# #-}
read# :: forall s (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
M# s a -> Int# -> State# s -> (# State# s, a #)
read# (MutablePrimArray# MutableByteArray# s
arr#) Int#
i# State# s
s0 = case MutableByteArray# s -> Int# -> State# s -> (# State# s, Word64# #)
forall d.
MutableByteArray# d -> Int# -> State# d -> (# State# d, Word64# #)
Exts.readWord64Array# MutableByteArray# s
arr# ((Int#
2# Int# -> Int# -> Int#
*# Int#
i#) Int# -> Int# -> Int#
+# Int#
1#) State# s
s0 of
  (# State# s
s1, Word64#
i0 #) -> case MutableByteArray# s -> Int# -> State# s -> (# State# s, Word64# #)
forall d.
MutableByteArray# d -> Int# -> State# d -> (# State# d, Word64# #)
Exts.readWord64Array# MutableByteArray# s
arr# (Int#
2# Int# -> Int# -> Int#
*# Int#
i#) State# s
s1 of
    (# State# s
s2, Word64#
i1 #) -> (# State# s
s2, (# Word64#, Word64# #) -> a
forall (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
(# Word64#, Word64# #) -> a
unsafeFromW128 (# Word64#
i0, Word64#
i1 #) #)

write# :: forall (s :: Type) (a :: TYPE R). M# s a -> Int# -> a -> State# s -> State# s
{-# inline write# #-}
write# :: forall s (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
M# s a -> Int# -> a -> State# s -> State# s
write# (MutablePrimArray# MutableByteArray# s
arr#) Int#
i# a
x State# s
s0 = case a -> (# Word64#, Word64# #)
forall (a :: TYPE ('TupleRep '[ 'Word64Rep, 'Word64Rep])).
a -> (# Word64#, Word64# #)
unsafeToW128 a
x of
  (# Word64#
a, Word64#
b #) -> case MutableByteArray# s -> Int# -> Word64# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word64# -> State# d -> State# d
Exts.writeWord64Array# MutableByteArray# s
arr# ((Int#
2# Int# -> Int# -> Int#
*# Int#
i#) Int# -> Int# -> Int#
+# Int#
1#) Word64#
a State# s
s0 of
    State# s
s1 -> case MutableByteArray# s -> Int# -> Word64# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word64# -> State# d -> State# d
Exts.writeWord64Array# MutableByteArray# s
arr# (Int#
2# Int# -> Int# -> Int#
*# Int#
i#) Word64#
b State# s
s1 of
      State# s
s2 -> State# s
s2
#endif