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

-- Note: In this module, we assume that Word is a 64-bit number.
-- It is not hard to correct this assumption with CPP, but this will
-- not be done until someones needs to run this on a 32-bit platform.
--
-- Note: A slightly longer-term goal is to preserve an invariant that
-- any unused trailing bits (there are between 0 and 63 of them in
-- any bit vector) are all zero. Currently, their values are undefined.
-- If they are all zero, then certain read-only operations become
-- faster. For example:
--
-- * Testing that two bit vectors are equal
-- * Testing if any bit in a bit vector is set to true
--
-- Some operations that produce vectors become slower, like @complement@
-- and @initialized@. Others, like @zipAnd@ and @zipOr@, naturally
-- preserve the invariant and do not require special code for the tail. 
--
-- If we start trying to preserve this invariant, we need to first write
-- failing tests that show where the invariant is not currently upheld.
-- At the least, @initialized@ and @unsafeShrinkFreeze@ need changes.
module Word1
  ( R
  , A#
  , M#
  , eq
  , eq#
  , 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# @'WordRep
type M# = MutablePrimArray# @'WordRep
type R = 'WordRep

eq :: forall (a :: TYPE R). a -> a -> Bool
{-# inline eq #-}
eq :: forall (a :: TYPE R). a -> a -> Bool
eq a
x a
y = Int# -> Bool
isTrue# (Word# -> Word# -> Int#
eqWord# (a -> Word#
forall (a :: TYPE R). a -> Word#
unsafeToWord a
x) (a -> Word#
forall (a :: TYPE R). a -> Word#
unsafeToWord a
y))

eq# :: forall (a :: TYPE R). a -> a -> Int#
{-# inline eq# #-}
eq# :: forall (a :: TYPE R). a -> a -> Int#
eq# a
x a
y = Word# -> Word# -> Int#
eqWord# (a -> Word#
forall (a :: TYPE R). a -> Word#
unsafeToWord a
x) (a -> Word#
forall (a :: TYPE R). a -> Word#
unsafeToWord a
y)

-- Precondition:
-- Argument is not negative
-- Postconditions:
-- First element is >=0, <n/64
-- Second element is >=0, <64
splitIndex_ :: Int# -> (# Int#, Int# #)
{-# inline splitIndex_ #-}
splitIndex_ :: Int# -> (# Int#, Int# #)
splitIndex_ Int#
bitIx = (# Int#
wordIx, Int#
intraWordIx #)
  where
  wordIx :: Int#
wordIx = Int#
bitIx Int# -> Int# -> Int#
`uncheckedIShiftRL#` Int#
6#
  intraWordIx :: Int#
intraWordIx = Int#
bitIx Int# -> Int# -> Int#
`andI#` Int#
0x3F#

-- Precondition: argument must be 0 or 1.
unsafeFromWord :: forall (a :: TYPE 'WordRep). Word# -> a
unsafeFromWord :: forall (a :: TYPE R). Word# -> a
unsafeFromWord Word#
x = Word# -> a
forall a b. a -> b
unsafeCoerce# Word#
x

unsafeToWord :: forall (a :: TYPE 'WordRep). a -> Word#
unsafeToWord :: forall (a :: TYPE R). a -> Word#
unsafeToWord a
x = a -> Word#
forall a b. a -> b
unsafeCoerce# a
x

internalIndex# :: ByteArray# -> Int# -> Word#
internalIndex# :: ByteArray# -> Int# -> Word#
internalIndex# ByteArray#
arr Int#
i =
  let !(# Int#
wordIx, Int#
intraWordIx #) = Int# -> (# Int#, Int# #)
splitIndex_ Int#
i
      !bitBundle :: Word#
bitBundle = ByteArray# -> Int# -> Word#
Exts.indexWordArray# ByteArray#
arr Int#
wordIx
   in Word# -> Word#
forall (a :: TYPE R). Word# -> a
unsafeFromWord ((Word#
bitBundle Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
intraWordIx) Word# -> Word# -> Word#
`and#` Word#
1## )

index# :: forall (a :: TYPE R). A# a -> Int# -> a
index# :: forall (a :: TYPE R). A# a -> Int# -> a
index# (PrimArray# ByteArray#
arr) Int#
i = Word# -> a
forall (a :: TYPE R). Word# -> a
unsafeFromWord (ByteArray# -> Int# -> Word#
internalIndex# ByteArray#
arr Int#
i)

read# :: forall (s :: Type) (a :: TYPE R).
  M# s a -> Int# -> State# s -> (# State# s, a #)
read# :: forall s (a :: TYPE R).
M# s a -> Int# -> State# s -> (# State# s, a #)
read# (MutablePrimArray# MutableByteArray# s
m) Int#
i State# s
st =
  let !(# Int#
wordIx, Int#
intraWordIx #) = Int# -> (# Int#, Int# #)
splitIndex_ Int#
i
      !(# State# s
st', Word#
bitBundle #) = MutableByteArray# s -> Int# -> State# s -> (# State# s, Word# #)
forall d.
MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
Exts.readWordArray# MutableByteArray# s
m Int#
wordIx State# s
st
   in (# State# s
st', Word# -> a
forall (a :: TYPE R). Word# -> a
unsafeFromWord ((Word#
bitBundle Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
intraWordIx) Word# -> Word# -> Word#
`and#` Word#
1## ) #)


write# :: forall (s :: Type) (a :: TYPE R).
  M# s a -> Int# -> a -> State# s -> State# s
write# :: forall s (a :: TYPE R). M# s a -> Int# -> a -> State# s -> State# s
write# (MutablePrimArray# MutableByteArray# s
arr) Int#
i a
v State# s
st =
  MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall s.
MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
internalWrite# MutableByteArray# s
arr Int#
i (a -> Word#
forall (a :: TYPE R). a -> Word#
unsafeToWord a
v) State# s
st

internalWrite# :: forall (s :: Type).
  MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
internalWrite# :: forall s.
MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
internalWrite# MutableByteArray# s
arr Int#
i Word#
v State# s
st =
  let !(# Int#
wordIx, Int#
intraWordIx #) = Int# -> (# Int#, Int# #)
splitIndex_ Int#
i
      !(# State# s
st', Word#
bitBundle #) = MutableByteArray# s -> Int# -> State# s -> (# State# s, Word# #)
forall d.
MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
Exts.readWordArray# MutableByteArray# s
arr Int#
wordIx State# s
st
      !mask :: Word#
mask = Word# -> Word#
not# (Word#
1## Word# -> Int# -> Word#
`uncheckedShiftL#` Int#
intraWordIx)
      !bitBundle' :: Word#
bitBundle' = (Word#
bitBundle Word# -> Word# -> Word#
`and#` Word#
mask) Word# -> Word# -> Word#
`or#` (Word#
v Word# -> Int# -> Word#
`uncheckedShiftL#` Int#
intraWordIx)
   in MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall s.
MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
Exts.writeWordArray# MutableByteArray# s
arr Int#
wordIx Word#
bitBundle' State# s
st'

empty# :: forall (a :: TYPE R). (# #) -> A# a
empty# :: forall (a :: TYPE R). (# #) -> A# a
empty# = (# #) -> PrimArray# a
forall a. (# #) -> PrimArray# a
emptyPrimArray#

unsafeFreeze# :: forall (s :: Type) (a :: TYPE R).
     M# s a
  -> State# s
  -> (# State# s, A# a #)
unsafeFreeze# :: forall s (a :: TYPE R). 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 #)

-- 
-- 
-- unsafeFreeze# :: forall (s :: Type) (a :: TYPE R).
--      M# s a
--   -> State# s
--   -> (# State# s, A# a #)
-- unsafeFreeze# (MutablePrimArray# m) s0 = case unsafeFreezeByteArray# m s0 of
--   (# s1, v #) -> (# s1, PrimArray# v #)
-- 
-- empty# :: forall (a :: TYPE R). (# #) -> A# a
-- empty# = emptyPrimArray#
-- 
--   (# s1, m #) -> case Exts.setByteArray# m 0# n (Exts.word2Int# (Exts.word8ToWord# (unsafeToW8 a))) s1 of
--     s2 -> (# s2, MutablePrimArray# m #)
-- 
-- set# :: forall (s :: Type) (a :: TYPE R).
--      M# s a
--   -> Int#
--   -> Int#
--   -> a
--   -> State# s
--   -> State# s
-- set# (MutablePrimArray# m) off0 len0 a s0 = Exts.setByteArray# m off0 len0 (Exts.word2Int# (Exts.word8ToWord# (unsafeToW8 a))) s0
-- 

-- shrink and freeze, all at once
unsafeShrinkFreeze# ::
     M# s a
  -> Int#
  -> State# s
  -> (# State# s, A# a #)
unsafeShrinkFreeze# :: forall s (a :: TYPE R).
M# s a -> Int# -> State# s -> (# State# s, A# a #)
unsafeShrinkFreeze# (MutablePrimArray# MutableByteArray# s
marr) Int#
sz State# s
st0 =
  case MutableByteArray# s -> State# s -> (# State# s, Int# #)
forall d. MutableByteArray# d -> State# d -> (# State# d, Int# #)
getSizeofMutableByteArray# MutableByteArray# s
marr State# s
st0 of
    (# State# s
st, Int#
oldSzBytes #) ->
      let !(# Int#
wordSz, Int#
subWordSz #) = Int# -> (# Int#, Int# #)
splitIndex_ Int#
sz
          !paddedSz :: Int#
paddedSz = Int#
wordSz Int# -> Int# -> Int#
+# if Int# -> Bool
isTrue# (Int#
subWordSz Int# -> Int# -> Int#
==# Int#
0#) then Int#
0# else Int#
1#
          !szBytes :: Int#
szBytes = Int#
paddedSz Int# -> Int# -> Int#
*# Int#
8#
          !st' :: State# s
st' = case Int#
szBytes Int# -> Int# -> Int#
==# Int#
oldSzBytes of
            Int#
1# -> State# s
st
            Int#
_ -> MutableByteArray# s -> Int# -> State# s -> State# s
forall d. MutableByteArray# d -> Int# -> State# d -> State# d
Exts.shrinkMutableByteArray# MutableByteArray# s
marr Int#
szBytes State# s
st
       in case MutableByteArray# s -> State# s -> (# State# s, ByteArray# #)
forall d.
MutableByteArray# d -> State# d -> (# State# d, ByteArray# #)
Exts.unsafeFreezeByteArray# MutableByteArray# s
marr State# s
st' of
            (# State# s
st'', ByteArray#
v #) -> (# State# s
st'', ByteArray# -> A# a
forall a. ByteArray# -> PrimArray# a
PrimArray# ByteArray#
v #)

-- thaw# :: forall (s :: Type) (a :: TYPE R).
--      A# a
--   -> Int#
--   -> Int#
--   -> State# s
--   -> (# State# s, M# s a #)
-- thaw# (PrimArray# v) off len s0 = case Exts.newByteArray# len s0 of
--   (# s1, m #) -> case Exts.copyByteArray# v off m 0# len s1 of
--     s2 -> (# s2, MutablePrimArray# m #)

set# :: forall (s :: Type) (a :: TYPE R).
     M# s a
  -> Int#
  -> Int#
  -> a
  -> State# s
  -> State# s
{-# inline set# #-}
set# :: forall s (a :: TYPE R).
M# s a -> Int# -> Int# -> a -> State# s -> State# s
set# parr :: M# s a
parr@(MutablePrimArray# MutableByteArray# s
arr) Int#
off0 Int#
len0 a
v State# s
st0 =
    let subOff :: Int#
subOff = Int#
off0 Int# -> Int# -> Int#
`andI#` Int#
7#
      -- set non-byte-aligned, initial bits
        len :: Int#
len = Int# -> Int# -> Int#
min# Int#
len0 (Int#
8# Int# -> Int# -> Int#
-# Int#
subOff)
        st' :: State# s
st' = Int# -> Int# -> State# s -> State# s
bitLoop Int#
off0 Int#
len State# s
st0
        -- set full bytes
        off' :: Int#
off' = Int#
off0 Int# -> Int# -> Int#
+# Int#
len
        len' :: Int#
len' = Int#
len0 Int# -> Int# -> Int#
-# Int#
len
        st'' :: State# s
st'' = Int# -> Int# -> State# s -> State# s
writeBytes Int#
off' Int#
len' State# s
st'
        -- set trailing bits smaller than a byte
        off'' :: Int#
off'' = Int#
off' Int# -> Int# -> Int#
+# ((Int#
len' Int# -> Int# -> Int#
`uncheckedIShiftRL#` Int#
3#) Int# -> Int# -> Int#
`uncheckedIShiftL#` Int#
3#)
        len'' :: Int#
len'' = Int#
len' Int# -> Int# -> Int#
`andI#` Int#
7#
     in Int# -> Int# -> State# s -> State# s
bitLoop Int#
off'' Int#
len'' State# s
st''
  where
  -- TODO could split bitLoop into writeBitsUnaligned and writeBitsAligned, which would use masking instead of a loop
  bitLoop :: Int# -> Int# -> State# s -> State# s
bitLoop Int#
_ Int#
0# State# s
st = State# s
st
  bitLoop Int#
off Int#
len State# s
st =
    let st' :: State# s
st' = M# s a -> Int# -> a -> State# s -> State# s
forall s (a :: TYPE R). M# s a -> Int# -> a -> State# s -> State# s
write# M# s a
parr Int#
off a
v State# s
st
     in Int# -> Int# -> State# s -> State# s
bitLoop (Int#
off Int# -> Int# -> Int#
+# Int#
1#) (Int#
len Int# -> Int# -> Int#
-# Int#
1#) State# s
st'
  writeBytes :: Int# -> Int# -> State# s -> State# s
writeBytes Int#
off Int#
len State# s
st =
    let !offB :: Int#
offB = Int#
off Int# -> Int# -> Int#
`uncheckedIShiftRL#` Int#
3#
        !lenB :: Int#
lenB = Int#
len Int# -> Int# -> Int#
`uncheckedIShiftRL#` Int#
3#
     in MutableByteArray# s -> Int# -> Int# -> Int# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Int# -> Int# -> State# d -> State# d
Exts.setByteArray# MutableByteArray# s
arr Int#
offB Int#
lenB Int#
vB State# s
st
  vB :: Int#
vB = case a -> Word#
forall (a :: TYPE R). a -> Word#
unsafeToWord a
v of
    Word#
0## -> Int#
0#
    Word#
_ -> Int#
0xFF#

-- TODO: Zero out any trailing bits. 
initialized# :: forall (s :: Type) (a :: TYPE R).
     Int#
  -> a
  -> State# s
  -> (# State# s, M# s a #)
initialized# :: forall s (a :: TYPE R).
Int# -> a -> State# s -> (# State# s, M# s a #)
initialized# Int#
sz a
v0 State# s
st =
  let !(# Int#
wordSz, Int#
subWordSz #) = Int# -> (# Int#, Int# #)
splitIndex_ Int#
sz
      !paddedSz :: Int#
paddedSz = Int#
wordSz Int# -> Int# -> Int#
+# if Int# -> Bool
isTrue# (Int#
subWordSz Int# -> Int# -> Int#
==# Int#
0#) then Int#
0# else Int#
1#
      !szBytes :: Int#
szBytes = Int#
paddedSz Int# -> Int# -> Int#
*# Int#
8#
      !(# State# s
st', MutableByteArray# s
marr #) = Int# -> State# s -> (# State# s, MutableByteArray# s #)
forall d. Int# -> State# d -> (# State# d, MutableByteArray# d #)
Exts.newByteArray# Int#
szBytes State# s
st
      !v :: Int#
v = case a -> Word#
forall (a :: TYPE R). a -> Word#
unsafeToWord a
v0 of
        Word#
0## -> Int#
0#
        Word#
_ -> Int#
0xFF#
      !st'' :: State# s
st'' = MutableByteArray# s -> Int# -> Int# -> Int# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Int# -> Int# -> State# d -> State# d
Exts.setByteArray# MutableByteArray# s
marr Int#
0# Int#
szBytes Int#
v State# s
st'
   in (# State# s
st'', MutableByteArray# s -> MutablePrimArray# s a
forall a b. MutableByteArray# a -> MutablePrimArray# a b
MutablePrimArray# MutableByteArray# s
marr #)

min# :: Int# -> Int# -> Int#
{-# inline min# #-}
min# :: Int# -> Int# -> Int#
min# Int#
a Int#
b = if Int# -> Bool
isTrue# (Int#
a Int# -> Int# -> Int#
<# Int#
b) then Int#
a else Int#
b

copy# :: forall (s :: Type) (a :: TYPE R).
     M# s a -- destination
  -> Int# -- destination offset
  -> A# a -- source
  -> Int# -- source offset
  -> Int# -- length
  -> State# s
  -> State# s
copy# :: forall s (a :: TYPE R).
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 State# s
st =
  MutableByteArray# s
-> Int# -> ByteArray# -> Int# -> Int# -> State# s -> State# s
forall s.
MutableByteArray# s
-> Int# -> ByteArray# -> Int# -> Int# -> State# s -> State# s
internalCopy# MutableByteArray# s
dst Int#
doff ByteArray#
src Int#
soff Int#
len State# s
st

internalCopy# :: MutableByteArray# s -> Int# -> ByteArray# -> Int# -> Int# -> State# s -> State# s
{-# inline copy# #-}
internalCopy# :: forall s.
MutableByteArray# s
-> Int# -> ByteArray# -> Int# -> Int# -> State# s -> State# s
internalCopy# MutableByteArray# s
dst Int#
0# ByteArray#
src Int#
0# Int#
len State# s
st =
-- TODO when soff == doff, we can do like set#
-- first align with naiveCopy, then copy by bytes, then copy the traling bits with naiveCopy
-- in fact, this can work even when soff - doff divisible by 8
  let !lenB :: Int#
lenB = Int#
len Int# -> Int# -> Int#
`uncheckedIShiftRL#` Int#
3#
      !st' :: State# s
st' = 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#
0# MutableByteArray# s
dst Int#
0# Int#
lenB State# s
st
      !off' :: Int#
off' = Int#
lenB Int# -> Int# -> Int#
`uncheckedIShiftL#` Int#
3#
      !len' :: Int#
len' = Int#
len Int# -> Int# -> Int#
`andI#` Int#
7#
   in MutableByteArray# s
-> Int# -> ByteArray# -> Int# -> Int# -> State# s -> State# s
forall s.
MutableByteArray# s
-> Int# -> ByteArray# -> Int# -> Int# -> State# s -> State# s
internalNaiveCopy# MutableByteArray# s
dst Int#
off' ByteArray#
src Int#
off' Int#
len' State# s
st'
internalCopy# MutableByteArray# s
dst Int#
doff ByteArray#
src Int#
soff Int#
len State# s
st = MutableByteArray# s
-> Int# -> ByteArray# -> Int# -> Int# -> State# s -> State# s
forall s.
MutableByteArray# s
-> Int# -> ByteArray# -> Int# -> Int# -> State# s -> State# s
internalNaiveCopy# MutableByteArray# s
dst Int#
doff ByteArray#
src Int#
soff Int#
len State# s
st

internalNaiveCopy# :: MutableByteArray# s -> Int# -> ByteArray# -> Int# -> Int# -> State# s -> State# s
-- TODO if I had an index64 :: ByteArray# -> off:Int#  -> len:Int# -> Int#
-- that reads up to `min len 64` unaligned bits starting at off
-- then I could write whole words at a time after aligning the doff, just as in set#
internalNaiveCopy# :: forall s.
MutableByteArray# s
-> Int# -> ByteArray# -> Int# -> Int# -> State# s -> State# s
internalNaiveCopy# MutableByteArray# s
_ Int#
_ ByteArray#
_ Int#
_ Int#
0# State# s
st = State# s
st
internalNaiveCopy# MutableByteArray# s
dst Int#
doff ByteArray#
src Int#
soff Int#
len State# s
st =
  let !v :: Word#
v = ByteArray# -> Int# -> Word#
internalIndex# ByteArray#
src Int#
soff
      !st' :: State# s
st' = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall s.
MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
internalWrite# MutableByteArray# s
dst Int#
doff Word#
v State# s
st
   in MutableByteArray# s
-> Int# -> ByteArray# -> Int# -> Int# -> State# s -> State# s
forall s.
MutableByteArray# s
-> Int# -> ByteArray# -> Int# -> Int# -> State# s -> State# s
internalNaiveCopy# MutableByteArray# s
dst (Int#
doff Int# -> Int# -> Int#
+# Int#
1#) ByteArray#
src (Int#
soff Int# -> Int# -> Int#
+# Int#
1#) (Int#
len Int# -> Int# -> Int#
-# Int#
1#) State# s
st'

-- This should be rewritten, but it works for now. At least its
-- correctness is clear.
thaw# :: forall (s :: Type) (a :: TYPE R).
     A# a
  -> Int#
  -> Int#
  -> State# s
  -> (# State# s, M# s a #)
thaw# :: forall s (a :: TYPE R).
A# a -> Int# -> Int# -> State# s -> (# State# s, M# s a #)
thaw# A# a
v Int#
off Int#
len State# s
s0 = case Int# -> a -> State# s -> (# State# s, M# s a #)
forall s (a :: TYPE R).
Int# -> a -> State# s -> (# State# s, M# s a #)
initialized# Int#
len (Word# -> a
forall (a :: TYPE R). Word# -> a
unsafeFromWord Word#
0## ) State# s
s0 of
  (# State# s
s1, M# s a
m #) -> case M# s a -> Int# -> A# a -> Int# -> Int# -> State# s -> State# s
forall s (a :: TYPE R).
M# s a -> Int# -> A# a -> Int# -> Int# -> State# s -> State# s
copy# M# s a
m Int#
0# A# a
v Int#
off Int#
len State# s
s1 of
    State# s
s2 -> (# State# s
s2, M# s a
m #)

freeze# :: forall (s :: Type) (a :: TYPE R).
     M# s a
  -> Int#
  -> Int#
  -> State# s
  -> (# State# s, A# a #)
freeze# :: forall s (a :: TYPE R).
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#
off of
  Int#
0# ->
    let !(# Int#
wordSz, Int#
subWordSz #) = Int# -> (# Int#, Int# #)
splitIndex_ Int#
len
        !paddedSz :: Int#
paddedSz = Int#
wordSz Int# -> Int# -> Int#
+# if Int# -> Bool
isTrue# (Int#
subWordSz Int# -> Int# -> Int#
==# Int#
0#) then Int#
0# else Int#
1#
        !szBytes :: Int#
szBytes = Int#
paddedSz Int# -> Int# -> Int#
*# Int#
8#
     in case Int# -> State# s -> (# State# s, MutableByteArray# s #)
forall d. Int# -> State# d -> (# State# d, MutableByteArray# d #)
Exts.newByteArray# Int#
szBytes 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#
0# MutableByteArray# s
m Int#
0# Int#
szBytes 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 #)
  Int#
_ -> [Char] -> (# State# s, A# a #)
forall a. [Char] -> a
errorWithoutStackTrace [Char]
"vext:imp:Word1.freeze#: write the non-zero case"