    {-# LANGUAGE CPP #-}
    {-# LANGUAGE NoImplicitPrelude #-}
    {-# LANGUAGE MagicHash #-}
    {-# LANGUAGE UnboxedTuples #-}
    {-# LANGUAGE BlockArguments #-}
    {-# LANGUAGE BangPatterns #-}
    {-# LANGUAGE MultiWayIf #-}
    {-# LANGUAGE LambdaCase #-}
    {-# LANGUAGE PolyKinds #-}
    {-# LANGUAGE KindSignatures #-}
    {-# OPTIONS_GHC -Wno-name-shadowing #-}

    module GHC.Num.WordArray where

    import GHC.Prim
    import GHC.Magic
    import GHC.Types
    import GHC.Num.Primitives

    #include "MachDeps.h"
    #include "WordSize.h"

    default ()

    -- | Unlifted array of Word
    type WordArray#        = ByteArray#
    type MutableWordArray# = MutableByteArray#

    data WordArray          = WordArray WordArray#
    data MutableWordArray s = MutableWordArray (MutableWordArray# s)

    -- | Convert limb count into byte count
    wordsToBytes# :: Int# -> Int#
    wordsToBytes# :: Int# -> Int#
    wordsToBytes# Int#
    i = Int#
    i Int# -> Int# -> Int#
    `uncheckedIShiftL#` WORD_SIZE_BYTES_SHIFT#

    -- | Convert byte count into limb count
    bytesToWords# :: Int# -> Int#
    bytesToWords# :: Int# -> Int#
    bytesToWords# Int#
    i = Int#
    i Int# -> Int# -> Int#
    `uncheckedIShiftRL#` WORD_SIZE_BYTES_SHIFT#

    -- | Create a new WordArray# of the given size (*in Word#*) and apply the
    -- action to it before returning it frozen
    withNewWordArray#
       :: Int#  -- ^ Size in Word
       -> (MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld)
       -> WordArray#
    withNewWordArray# :: Int#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> WordArray#
    withNewWordArray# Int#
    sz MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld
    act = case (State# RealWorld -> (# State# RealWorld, WordArray# #))
    -> (# State# RealWorld, WordArray# #)
    forall o. (State# RealWorld -> o) -> o
    runRW# State# RealWorld -> (# State# RealWorld, WordArray# #)
    io of (# State# RealWorld
    _, WordArray#
    a #) -> WordArray#
    a
       where
          io :: State# RealWorld -> (# State# RealWorld, WordArray# #)
    io State# RealWorld
    s =
             case Int#
    -> State# RealWorld
    -> (# State# RealWorld, MutableWordArray# RealWorld #)
    forall s. Int# -> State# s -> (# State# s, MutableWordArray# s #)
    newWordArray# Int#
    sz State# RealWorld
    s of { (# State# RealWorld
    s, MutableWordArray# RealWorld
    mwa #) ->
             case MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld
    act MutableWordArray# RealWorld
    mwa State# RealWorld
    s          of { State# RealWorld
    s ->
             MutableWordArray# RealWorld
    -> State# RealWorld -> (# State# RealWorld, WordArray# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, WordArray# #)
    unsafeFreezeByteArray# MutableWordArray# RealWorld
    mwa State# RealWorld
    s
             }}

    -- | Create two new WordArray# of the given sizes (*in Word#*) and apply the
    -- action to them before returning them frozen
    withNewWordArray2#
       :: Int# -- ^ Size in Word
       -> Int# -- ^ Ditto
       -> (MutableWordArray# RealWorld
          -> MutableWordArray# RealWorld
          -> State# RealWorld
          -> State# RealWorld)
       -> (# WordArray#, WordArray# #)
    withNewWordArray2# :: Int#
    -> Int#
    -> (MutableWordArray# RealWorld
        -> MutableWordArray# RealWorld
        -> State# RealWorld
        -> State# RealWorld)
    -> (# WordArray#, WordArray# #)
    withNewWordArray2# Int#
    sz1 Int#
    sz2 MutableWordArray# RealWorld
    -> MutableWordArray# RealWorld
    -> State# RealWorld
    -> State# RealWorld
    act = case (State# RealWorld
     -> (# State# RealWorld, (# WordArray#, WordArray# #) #))
    -> (# State# RealWorld, (# WordArray#, WordArray# #) #)
    forall o. (State# RealWorld -> o) -> o
    runRW# State# RealWorld
    -> (# State# RealWorld, (# WordArray#, WordArray# #) #)
    io of (# State# RealWorld
    _, (# WordArray#, WordArray# #)
    a #) -> (# WordArray#, WordArray# #)
    a
       where
          io :: State# RealWorld
    -> (# State# RealWorld, (# WordArray#, WordArray# #) #)
    io State# RealWorld
    s =
             case Int#
    -> State# RealWorld
    -> (# State# RealWorld, MutableWordArray# RealWorld #)
    forall s. Int# -> State# s -> (# State# s, MutableWordArray# s #)
    newWordArray# Int#
    sz1 State# RealWorld
    s of { (# State# RealWorld
    s, MutableWordArray# RealWorld
    mwa1 #) ->
             case Int#
    -> State# RealWorld
    -> (# State# RealWorld, MutableWordArray# RealWorld #)
    forall s. Int# -> State# s -> (# State# s, MutableWordArray# s #)
    newWordArray# Int#
    sz2 State# RealWorld
    s of { (# State# RealWorld
    s, MutableWordArray# RealWorld
    mwa2 #) ->
             case MutableWordArray# RealWorld
    -> MutableWordArray# RealWorld
    -> State# RealWorld
    -> State# RealWorld
    act MutableWordArray# RealWorld
    mwa1 MutableWordArray# RealWorld
    mwa2 State# RealWorld
    s     of { State# RealWorld
    s ->
             case MutableWordArray# RealWorld
    -> State# RealWorld -> (# State# RealWorld, WordArray# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, WordArray# #)
    unsafeFreezeByteArray# MutableWordArray# RealWorld
    mwa1 State# RealWorld
    s of { (# State# RealWorld
    s, WordArray#
    wa1 #) ->
             case MutableWordArray# RealWorld
    -> State# RealWorld -> (# State# RealWorld, WordArray# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, WordArray# #)
    unsafeFreezeByteArray# MutableWordArray# RealWorld
    mwa2 State# RealWorld
    s of { (# State# RealWorld
    s, WordArray#
    wa2 #) ->
                (# State# RealWorld
    s, (# WordArray#
    wa1, WordArray#
    wa2 #) #)
             }}}}}

    -- | Create a new WordArray#
    newWordArray# :: Int# -> State# s -> (# State# s, MutableWordArray# s #)
    newWordArray# :: forall s. Int# -> State# s -> (# State# s, MutableWordArray# s #)
    newWordArray# Int#
    sz State# s
    s = Int# -> State# s -> (# State# s, MutableByteArray# s #)
    forall s. Int# -> State# s -> (# State# s, MutableWordArray# s #)
    newByteArray# (Int# -> Int#
    wordsToBytes# Int#
    sz) State# s
    s

    -- | Create a new WordArray# of the given size (*in Word#*), apply the action to
    -- it, trim its most significant zeroes, then return it frozen
    withNewWordArrayTrimmed#
       :: Int#  -- ^ Size in Word
       -> (MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld)
       -> WordArray#
    withNewWordArrayTrimmed# :: Int#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> WordArray#
    withNewWordArrayTrimmed# Int#
    sz MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld
    act = Int#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> WordArray#
    withNewWordArray# Int#
    sz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
       case MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld
    act MutableWordArray# RealWorld
    mwa State# RealWorld
    s of
          State# RealWorld
    s' -> MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld
    forall s. MutableByteArray# s -> State# s -> State# s
    mwaTrimZeroes# MutableWordArray# RealWorld
    mwa State# RealWorld
    s'

    -- | Create two new WordArray# of the given sizes (*in Word#*), apply the action
    -- to them, trim their most significant zeroes, then return them frozen
    withNewWordArray2Trimmed#
       :: Int#  -- ^ Size in Word
       -> Int#  -- ^ Ditto
       -> (MutableWordArray# RealWorld
          -> MutableWordArray# RealWorld
          -> State# RealWorld
          -> State# RealWorld)
       -> (# WordArray#, WordArray# #)
    withNewWordArray2Trimmed# :: Int#
    -> Int#
    -> (MutableWordArray# RealWorld
        -> MutableWordArray# RealWorld
        -> State# RealWorld
        -> State# RealWorld)
    -> (# WordArray#, WordArray# #)
    withNewWordArray2Trimmed# Int#
    sz1 Int#
    sz2 MutableWordArray# RealWorld
    -> MutableWordArray# RealWorld
    -> State# RealWorld
    -> State# RealWorld
    act = Int#
    -> Int#
    -> (MutableWordArray# RealWorld
        -> MutableWordArray# RealWorld
        -> State# RealWorld
        -> State# RealWorld)
    -> (# WordArray#, WordArray# #)
    withNewWordArray2# Int#
    sz1 Int#
    sz2 \MutableWordArray# RealWorld
    mwa1 MutableWordArray# RealWorld
    mwa2 State# RealWorld
    s ->
       case MutableWordArray# RealWorld
    -> MutableWordArray# RealWorld
    -> State# RealWorld
    -> State# RealWorld
    act MutableWordArray# RealWorld
    mwa1 MutableWordArray# RealWorld
    mwa2 State# RealWorld
    s of
          State# RealWorld
    s' -> case MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld
    forall s. MutableByteArray# s -> State# s -> State# s
    mwaTrimZeroes# MutableWordArray# RealWorld
    mwa1 State# RealWorld
    s' of
             State# RealWorld
    s'' -> MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld
    forall s. MutableByteArray# s -> State# s -> State# s
    mwaTrimZeroes# MutableWordArray# RealWorld
    mwa2 State# RealWorld
    s''

    -- | Create a new WordArray# of the given size (*in Word#*), apply the action to
    -- it. If the action returns true#, trim its most significant zeroes, then
    -- return it frozen. Otherwise, return ().
    withNewWordArrayTrimmedMaybe#
       :: Int#  -- ^ Size in Word
       -> (MutableWordArray# RealWorld -> State# RealWorld -> (# State# RealWorld, Bool# #))
       -> (# (# #) | WordArray# #)
    withNewWordArrayTrimmedMaybe# :: Int#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> (# State# RealWorld, Int# #))
    -> (# (# #) | WordArray# #)
    withNewWordArrayTrimmedMaybe# Int#
    sz MutableWordArray# RealWorld
    -> State# RealWorld -> (# State# RealWorld, Int# #)
    act = case (State# RealWorld
     -> (# State# RealWorld, (# (# #) | WordArray# #) #))
    -> (# State# RealWorld, (# (# #) | WordArray# #) #)
    forall o. (State# RealWorld -> o) -> o
    runRW# State# RealWorld
    -> (# State# RealWorld, (# (# #) | WordArray# #) #)
    io of (# State# RealWorld
    _, (# (# #) | WordArray# #)
    a #) -> (# (# #) | WordArray# #)
    a
       where
          io :: State# RealWorld
    -> (# State# RealWorld, (# (# #) | WordArray# #) #)
    io State# RealWorld
    s =
             case Int#
    -> State# RealWorld
    -> (# State# RealWorld, MutableWordArray# RealWorld #)
    forall s. Int# -> State# s -> (# State# s, MutableWordArray# s #)
    newWordArray# Int#
    sz State# RealWorld
    s of
                (# State# RealWorld
    s, MutableWordArray# RealWorld
    mwa #) -> case MutableWordArray# RealWorld
    -> State# RealWorld -> (# State# RealWorld, Int# #)
    act MutableWordArray# RealWorld
    mwa State# RealWorld
    s of
                   (# State# RealWorld
    s, Int#
    0# #) -> (# State# RealWorld
    s, (# (# #) | #) #)
                   (# State# RealWorld
    s, Int#
    _  #) -> case MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld
    forall s. MutableByteArray# s -> State# s -> State# s
    mwaTrimZeroes# MutableWordArray# RealWorld
    mwa State# RealWorld
    s of
                      State# RealWorld
    s -> case MutableWordArray# RealWorld
    -> State# RealWorld -> (# State# RealWorld, WordArray# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, WordArray# #)
    unsafeFreezeByteArray# MutableWordArray# RealWorld
    mwa State# RealWorld
    s of
                         (# State# RealWorld
    s, WordArray#
    ba #) -> (# State# RealWorld
    s, (# | WordArray#
    ba #) #)

    -- | Create a WordArray# from two Word#
    --
    -- `wordArrayFromWord2# h l
    --    where h is the most significant word
    --          l is the least significant word
    wordArrayFromWord2# :: Word# -> Word# -> WordArray#
    wordArrayFromWord2# :: Word# -> Word# -> WordArray#
    wordArrayFromWord2# Word#
    h Word#
    l   =
       Int#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> WordArray#
    withNewWordArray# Int#
    2# \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
          case MutableWordArray# RealWorld
    -> Int# -> Word# -> State# RealWorld -> State# RealWorld
    forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# RealWorld
    mwa Int#
    0# Word#
    l State# RealWorld
    s of
             State# RealWorld
    s -> MutableWordArray# RealWorld
    -> Int# -> Word# -> State# RealWorld -> State# RealWorld
    forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# RealWorld
    mwa Int#
    1# Word#
    h State# RealWorld
    s

    -- | Create a WordArray# from one Word#
    wordArrayFromWord# :: Word# -> WordArray#
    wordArrayFromWord# :: Word# -> WordArray#
    wordArrayFromWord# Word#
    w   =
       Int#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> WordArray#
    withNewWordArray# Int#
    1# \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
          MutableWordArray# RealWorld
    -> Int# -> Word# -> State# RealWorld -> State# RealWorld
    forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# RealWorld
    mwa Int#
    0# Word#
    w State# RealWorld
    s

    -- | Word array size
    wordArraySize# :: WordArray# -> Int#
    wordArraySize# :: WordArray# -> Int#
    wordArraySize# WordArray#
    ba = Int# -> Int#
    bytesToWords# (WordArray# -> Int#
    sizeofByteArray# WordArray#
    ba)

    -- | Equality test for WordArray#

    -- | Get size in Words
    mwaSize# :: MutableWordArray# s-> State# s -> (# State# s, Int# #)
    mwaSize# :: forall s. MutableWordArray# s -> State# s -> (# State# s, Int# #)
    mwaSize# MutableWordArray# s
    mba State# s
    s = case MutableWordArray# s -> State# s -> (# State# s, Int# #)
    forall s. MutableWordArray# s -> State# s -> (# State# s, Int# #)
    getSizeofMutableByteArray# MutableWordArray# s
    mba State# s
    s of
       (# State# s
    s2, Int#
    sz #) -> (# State# s
    s2, Int# -> Int#
    bytesToWords# Int#
    sz #)

    -- | Get the last Word (must be non empty!)
    wordArrayLast# :: WordArray# -> Word#
    wordArrayLast# :: WordArray# -> Word#
    wordArrayLast# WordArray#
    a = WordArray# -> Int# -> Word#
    indexWordArray# WordArray#
    a (WordArray# -> Int#
    wordArraySize# WordArray#
    a Int# -> Int# -> Int#
    -# Int#
    1#)

    -- | Copy Words from a WordArray
    --
    -- Don't do anything if the number of words to copy is <= 0
    mwaArrayCopy# :: MutableByteArray# s -> Int# -> WordArray# -> Int# -> Int# -> State# s -> State# s
    mwaArrayCopy# :: forall s.
    MutableByteArray# s
    -> Int# -> WordArray# -> Int# -> Int# -> State# s -> State# s
    mwaArrayCopy# MutableByteArray# s
    dst Int#
    dstIdx WordArray#
    src Int#
    srcIdx Int#
    n State# s
    s
       | Int# -> Bool
    isTrue# (Int#
    n Int# -> Int# -> Int#
    <=# Int#
    0#) = State# s
    s
       | Bool
    True = WordArray#
    -> Int#
    -> MutableByteArray# s
    -> Int#
    -> Int#
    -> State# s
    -> State# s
    forall d.
    WordArray#
    -> Int#
    -> MutableByteArray# d
    -> Int#
    -> Int#
    -> State# d
    -> State# d
    copyByteArray#
                   WordArray#
    src (Int# -> Int#
    wordsToBytes# Int#
    srcIdx)
                   MutableByteArray# s
    dst (Int# -> Int#
    wordsToBytes# Int#
    dstIdx)
                   (Int# -> Int#
    wordsToBytes# Int#
    n) State# s
    s

    -- | Shrink last words of a WordArray
    mwaShrink# :: MutableByteArray# s -> Int# -> State# s -> State# s
    mwaShrink# :: forall s. MutableByteArray# s -> Int# -> State# s -> State# s
    mwaShrink# MutableByteArray# s
    _mwa Int#
    0# State# s
    s = State# s
    s
    mwaShrink# MutableByteArray# s
    mwa  Int#
    i  State# s
    s =
       case MutableByteArray# s -> State# s -> (# State# s, Int# #)
    forall s. MutableWordArray# s -> State# s -> (# State# s, Int# #)
    mwaSize# MutableByteArray# s
    mwa State# s
    s of
          (# State# s
    s, Int#
    n #) -> MutableByteArray# s -> Int# -> State# s -> State# s
    forall s. MutableByteArray# s -> Int# -> State# s -> State# s
    shrinkMutableByteArray# MutableByteArray# s
    mwa (Int# -> Int#
    wordsToBytes# (Int#
    n Int# -> Int# -> Int#
    -# Int#
    i)) State# s
    s

    -- | Set size
    mwaSetSize# :: MutableByteArray# s -> Int# -> State# s -> State# s
    mwaSetSize# :: forall s. MutableByteArray# s -> Int# -> State# s -> State# s
    mwaSetSize# MutableByteArray# s
    mwa Int#
    n State# s
    s = MutableByteArray# s -> Int# -> State# s -> State# s
    forall s. MutableByteArray# s -> Int# -> State# s -> State# s
    shrinkMutableByteArray# MutableByteArray# s
    mwa (Int# -> Int#
    wordsToBytes# Int#
    n) State# s
    s

    -- | Copy the WordArray into the MWA and shrink the size of MWA to the one of
    -- the WordArray
    mwaInitCopyShrink# :: MutableByteArray# s -> WordArray# -> State# s -> State# s
    mwaInitCopyShrink# :: forall s. MutableByteArray# s -> WordArray# -> State# s -> State# s
    mwaInitCopyShrink# MutableByteArray# s
    mwa WordArray#
    wa State# s
    s =
       case MutableByteArray# s
    -> Int# -> WordArray# -> Int# -> Int# -> State# s -> State# s
    forall s.
    MutableByteArray# s
    -> Int# -> WordArray# -> Int# -> Int# -> State# s -> State# s
    mwaArrayCopy# MutableByteArray# s
    mwa Int#
    0# WordArray#
    wa Int#
    0# (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) State# s
    s of
          State# s
    s -> MutableByteArray# s -> Int# -> State# s -> State# s
    forall s. MutableByteArray# s -> Int# -> State# s -> State# s
    mwaSetSize# MutableByteArray# s
    mwa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) State# s
    s

    -- | Trim ending zeroes
    mwaTrimZeroes# :: MutableByteArray# s -> State# s -> State# s
    mwaTrimZeroes# :: forall s. MutableByteArray# s -> State# s -> State# s
    mwaTrimZeroes# MutableByteArray# s
    mwa State# s
    s1 =
       case MutableByteArray# s -> State# s -> (# State# s, Int# #)
    forall s. MutableWordArray# s -> State# s -> (# State# s, Int# #)
    mwaClz MutableByteArray# s
    mwa State# s
    s1 of
          (# State# s
    s2, Int#
    0# #) -> State# s
    s2
          (# State# s
    s2, Int#
    c  #) -> MutableByteArray# s -> Int# -> State# s -> State# s
    forall s. MutableByteArray# s -> Int# -> State# s -> State# s
    mwaShrink# MutableByteArray# s
    mwa Int#
    c State# s
    s2

    -- | Count leading zero Words
    mwaClz :: MutableWordArray# s -> State# s -> (# State# s, Int# #)
    mwaClz :: forall s. MutableWordArray# s -> State# s -> (# State# s, Int# #)
    mwaClz MutableWordArray# s
    mwa State# s
    s1 = case MutableWordArray# s -> State# s -> (# State# s, Int# #)
    forall s. MutableWordArray# s -> State# s -> (# State# s, Int# #)
    mwaSize# MutableWordArray# s
    mwa State# s
    s1 of
       (# State# s
    s2,Int#
    sz #)  -> MutableWordArray# s -> Int# -> State# s -> (# State# s, Int# #)
    forall s.
    MutableWordArray# s -> Int# -> State# s -> (# State# s, Int# #)
    mwaClzAt MutableWordArray# s
    mwa (Int#
    sz Int# -> Int# -> Int#
    -# Int#
    1#) State# s
    s2

    -- | Count leading zero Words starting at given position
    mwaClzAt :: MutableWordArray# s -> Int# -> State# s -> (# State# s, Int# #)
    mwaClzAt :: forall s.
    MutableWordArray# s -> Int# -> State# s -> (# State# s, Int# #)
    mwaClzAt MutableWordArray# s
    mwa = Int# -> Int# -> State# s -> (# State# s, Int# #)
    go Int#
    0#
       where
          go :: Int# -> Int# -> State# s -> (# State# s, Int# #)
    go Int#
    c Int#
    i State# s
    s
             | Int# -> Bool
    isTrue# (Int#
    i Int# -> Int# -> Int#
    <# Int#
    0#) = (# State# s
    s, Int#
    c #)
             | Bool
    True = case MutableWordArray# s -> Int# -> State# s -> (# State# s, Word# #)
    forall d.
    MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
    readWordArray# MutableWordArray# s
    mwa Int#
    i State# s
    s of
                (# State# s
    s', Word#
    0## #) -> Int# -> Int# -> State# s -> (# State# s, Int# #)
    go (Int#
    c Int# -> Int# -> Int#
    +# Int#
    1#) (Int#
    i Int# -> Int# -> Int#
    -# Int#
    1#) State# s
    s'
                (# State# s
    s', Word#
    _   #) -> (# State# s
    s', Int#
    c #)

    -- | Count leading zero Words starting at given position
    waClzAt :: WordArray# -> Int# -> Int#
    waClzAt :: WordArray# -> Int# -> Int#
    waClzAt WordArray#
    wa = Int# -> Int# -> Int#
    go Int#
    0#
       where
          go :: Int# -> Int# -> Int#
    go Int#
    c Int#
    i
             | Int# -> Bool
    isTrue# (Int#
    i Int# -> Int# -> Int#
    <# Int#
    0#)
             = Int#
    c

             | Word#
    0## <- WordArray# -> Int# -> Word#
    indexWordArray# WordArray#
    wa Int#
    i
             = Int# -> Int# -> Int#
    go (Int#
    c Int# -> Int# -> Int#
    +# Int#
    1#) (Int#
    i Int# -> Int# -> Int#
    -# Int#
    1#)

             | Bool
    True
             = Int#
    c

    -- | Compare the most signiciant limbs of a and b. The comparison stops (i.e.
    -- returns EQ) when there isn't enough lims in a or b to perform another
    -- comparison.
    wordArrayCompareMSWords :: WordArray# -> WordArray# -> Ordering
    wordArrayCompareMSWords :: WordArray# -> WordArray# -> Ordering
    wordArrayCompareMSWords WordArray#
    wa WordArray#
    wb
       | Int#
    0# <- Int#
    szA
       , Int#
    0# <- Int#
    szB
       = Ordering
    EQ

       | Int#
    0# <- Int#
    szA
       = Ordering
    LT

       | Int#
    0# <- Int#
    szB
       = Ordering
    GT

       | Bool
    True
       = Int# -> Int# -> Ordering
    go (Int#
    szA Int# -> Int# -> Int#
    -# Int#
    1#) (Int#
    szB Int# -> Int# -> Int#
    -# Int#
    1#)
       where
          szA :: Int#
    szA  = WordArray# -> Int#
    wordArraySize# WordArray#
    wa
          szB :: Int#
    szB  = WordArray# -> Int#
    wordArraySize# WordArray#
    wb

          go :: Int# -> Int# -> Ordering
    go Int#
    i Int#
    j
             | Int# -> Bool
    isTrue# (Int#
    i Int# -> Int# -> Int#
    <# Int#
    0#) = Ordering
    EQ
             | Int# -> Bool
    isTrue# (Int#
    j Int# -> Int# -> Int#
    <# Int#
    0#) = Ordering
    EQ
             | Bool
    True =
                let
                   a :: Word#
    a = WordArray# -> Int# -> Word#
    indexWordArray# WordArray#
    wa Int#
    i
                   b :: Word#
    b = WordArray# -> Int# -> Word#
    indexWordArray# WordArray#
    wb Int#
    j
                in if | Int# -> Bool
    isTrue# (Word#
    a Word# -> Word# -> Int#
    `gtWord#` Word#
    b) -> Ordering
    GT
                      | Int# -> Bool
    isTrue# (Word#
    b Word# -> Word# -> Int#
    `gtWord#` Word#
    a) -> Ordering
    LT
                      | Bool
    True                    -> Int# -> Int# -> Ordering
    go (Int#
    i Int# -> Int# -> Int#
    -# Int#
    1#) (Int#
    j Int# -> Int# -> Int#
    -# Int#
    1#)

    -- | Compute MutableWordArray <- WordArray + Word
    --
    -- The MutableWordArray may not be initialized and will be erased anyway.
    --
    -- Input: Size(MutableWordArray) = Size(WordArray) + 1
    -- Output: Size(MutableWordArray) = Size(WordArray) [+ 1]
    mwaInitArrayPlusWord :: MutableWordArray# s -> WordArray# -> Word# -> State# s -> State#s
    mwaInitArrayPlusWord :: forall s.
    MutableWordArray# s -> WordArray# -> Word# -> State# s -> State# s
    mwaInitArrayPlusWord MutableWordArray# s
    mwa WordArray#
    wa = Int# -> Word# -> State# s -> State# s
    go Int#
    0#
       where
          sz :: Int#
    sz = WordArray# -> Int#
    wordArraySize# WordArray#
    wa
          go :: Int# -> Word# -> State# s -> State# s
    go Int#
    i Word#
    carry State# s
    s
             | Int# -> Bool
    isTrue# (Int#
    i Int# -> Int# -> Int#
    ># Int#
    sz)  = State# s
    s
             | Int# -> Bool
    isTrue# (Int#
    i Int# -> Int# -> Int#
    ==# Int#
    sz) = MutableWordArray# s -> Word# -> Int# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Word# -> Int# -> State# s -> State# s
    mwaWriteOrShrink MutableWordArray# s
    mwa Word#
    carry Int#
    i State# s
    s
             | Word#
    0## <- Word#
    carry       = -- copy higher remaining words and shrink the mwa
                                    case MutableWordArray# s
    -> Int# -> WordArray# -> Int# -> Int# -> State# s -> State# s
    forall s.
    MutableByteArray# s
    -> Int# -> WordArray# -> Int# -> Int# -> State# s -> State# s
    mwaArrayCopy# MutableWordArray# s
    mwa Int#
    i WordArray#
    wa Int#
    i (Int#
    sz Int# -> Int# -> Int#
    -# Int#
    i) State# s
    s of
                                        State# s
    s2 -> MutableWordArray# s -> Int# -> State# s -> State# s
    forall s. MutableByteArray# s -> Int# -> State# s -> State# s
    mwaShrink# MutableWordArray# s
    mwa Int#
    1# State# s
    s2
             | Bool
    True               = let !(# Word#
    l,Int#
    c #) = Word# -> Word# -> (# Word#, Int# #)
    addWordC# (WordArray# -> Int# -> Word#
    indexWordArray# WordArray#
    wa Int#
    i) Word#
    carry
                                    in case MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# s
    mwa Int#
    i Word#
    l State# s
    s of
                                        State# s
    s2 -> Int# -> Word# -> State# s -> State# s
    go (Int#
    i Int# -> Int# -> Int#
    +# Int#
    1#) (Int# -> Word#
    int2Word# Int#
    c) State# s
    s2

    -- | Write the most-significant Word:
    --    * if it is 0: shrink the array of 1 Word
    --    * otherwise: write it
    mwaWriteOrShrink :: MutableWordArray# s -> Word# -> Int# -> State# s -> State# s
    mwaWriteOrShrink :: forall s.
    MutableWordArray# s -> Word# -> Int# -> State# s -> State# s
    mwaWriteOrShrink MutableWordArray# s
    mwa Word#
    0## Int#
    _i State# s
    s = MutableWordArray# s -> Int# -> State# s -> State# s
    forall s. MutableByteArray# s -> Int# -> State# s -> State# s
    mwaShrink# MutableWordArray# s
    mwa Int#
    1# State# s
    s
    mwaWriteOrShrink MutableWordArray# s
    mwa  Word#
    w   Int#
    i State# s
    s = MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# s
    mwa Int#
    i Word#
    w State# s
    s

    -- | Compute the index of the most-significant Word and write it.
    mwaWriteMostSignificant :: MutableWordArray# s -> Word# -> State# s -> State# s
    mwaWriteMostSignificant :: forall s. MutableWordArray# s -> Word# -> State# s -> State# s
    mwaWriteMostSignificant MutableWordArray# s
    mwa Word#
    w State# s
    s =
       case MutableWordArray# s -> State# s -> (# State# s, Int# #)
    forall s. MutableWordArray# s -> State# s -> (# State# s, Int# #)
    mwaSize# MutableWordArray# s
    mwa State# s
    s of
          (# State# s
    s', Int#
    sz #) -> MutableWordArray# s -> Word# -> Int# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Word# -> Int# -> State# s -> State# s
    mwaWriteOrShrink MutableWordArray# s
    mwa Word#
    w (Int#
    sz Int# -> Int# -> Int#
    -# Int#
    1#) State# s
    s'

    -- | MutableWordArray <- zipWith op wa1 wa2
    --
    -- Required output: Size(MutableWordArray) = min Size(wa1) Size(wa2)
    mwaInitArrayBinOp :: MutableWordArray# s -> WordArray# -> WordArray# -> (Word# -> Word# -> Word#) -> State# s -> State#s
    mwaInitArrayBinOp :: forall s.
    MutableWordArray# s
    -> WordArray#
    -> WordArray#
    -> (Word# -> Word# -> Word#)
    -> State# s
    -> State# s
    mwaInitArrayBinOp MutableWordArray# s
    mwa WordArray#
    wa WordArray#
    wb Word# -> Word# -> Word#
    op State# s
    s = Int# -> State# s -> State# s
    go Int#
    0# State# s
    s
       where
          !sz :: Int#
    sz = Int# -> Int# -> Int#
    minI# (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) (WordArray# -> Int#
    wordArraySize# WordArray#
    wb)
          go :: Int# -> State# s -> State# s
    go Int#
    i State# s
    s'
             | Int# -> Bool
    isTrue# (Int#
    i Int# -> Int# -> Int#
    ==# Int#
    sz) = State# s
    s'
             | Bool
    True =
                case WordArray# -> Int# -> Word#
    indexWordArray# WordArray#
    wa Int#
    i Word# -> Word# -> Word#
    `op` WordArray# -> Int# -> Word#
    indexWordArray# WordArray#
    wb Int#
    i of
                   Word#
    v -> case MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# s
    mwa Int#
    i Word#
    v State# s
    s' of
                      State# s
    s'' -> Int# -> State# s -> State# s
    go (Int#
    i Int# -> Int# -> Int#
    +# Int#
    1#) State# s
    s''

    -- | Write an element of the MutableWordArray
    mwaWrite# :: MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    mwaWrite# :: forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    mwaWrite# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    writeWordArray#

    -- | Fill some part of a MutableWordArray with the given Word#
    mwaFill# :: MutableWordArray# s -> Word# -> Word# -> Word# -> State# s -> State# s
    mwaFill# :: forall s.
    MutableWordArray# s
    -> Word# -> Word# -> Word# -> State# s -> State# s
    mwaFill# MutableWordArray# s
    _   Word#
    _ Word#
    _   Word#
    0## State# s
    s = State# s
    s
    mwaFill# MutableWordArray# s
    mwa Word#
    v Word#
    off Word#
    n   State# s
    s = case MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# s
    mwa (Word# -> Int#
    word2Int# Word#
    off) Word#
    v State# s
    s of
       State# s
    s' -> MutableWordArray# s
    -> Word# -> Word# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s
    -> Word# -> Word# -> Word# -> State# s -> State# s
    mwaFill# MutableWordArray# s
    mwa Word#
    v (Word#
    off Word# -> Word# -> Word#
    `plusWord#` Word#
    1##) (Word#
    n Word# -> Word# -> Word#
    `minusWord#` Word#
    1##) State# s
    s'

    -- | Add Word# inplace (a the specified offset) in the mwa with carry propagation.
    mwaAddInplaceWord# :: MutableWordArray# d -> Int# -> Word# -> State# d -> State# d
    mwaAddInplaceWord# :: forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    mwaAddInplaceWord#   MutableWordArray# d
    _ Int#
    _ Word#
    0## State# d
    s = State# d
    s
    mwaAddInplaceWord# MutableWordArray# d
    mwa Int#
    i Word#
    y   State# d
    s = case MutableWordArray# d -> Int# -> State# d -> (# State# d, Word# #)
    forall d.
    MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
    readWordArray# MutableWordArray# d
    mwa Int#
    i State# d
    s of
       (# State# d
    s1, Word#
    x #) -> let !(# Word#
    h,Word#
    l #) = Word# -> Word# -> (# Word#, Word# #)
    plusWord2# Word#
    x Word#
    y
                      in case MutableWordArray# d -> Int# -> Word# -> State# d -> State# d
    forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# d
    mwa Int#
    i Word#
    l State# d
    s1 of
                            State# d
    s2 -> MutableWordArray# d -> Int# -> Word# -> State# d -> State# d
    forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    mwaAddInplaceWord# MutableWordArray# d
    mwa (Int#
    i Int# -> Int# -> Int#
    +# Int#
    1#) Word#
    h State# d
    s2

    -- | Sub Word# inplace (at the specified offset) in the mwa with carry
    -- propagation.
    --
    -- Return False# on underflow
    mwaSubInplaceWord#
       :: MutableWordArray# d
       -> Int#
       -> Word#
       -> State# d
       -> (# State# d, Bool# #)
    mwaSubInplaceWord# :: forall d.
    MutableWordArray# d
    -> Int# -> Word# -> State# d -> (# State# d, Int# #)
    mwaSubInplaceWord# MutableWordArray# d
    mwa Int#
    ii Word#
    iw State# d
    s1 = case MutableWordArray# d -> State# d -> (# State# d, Int# #)
    forall s. MutableWordArray# s -> State# s -> (# State# s, Int# #)
    mwaSize# MutableWordArray# d
    mwa State# d
    s1 of
       (# State# d
    is, Int#
    sz #) ->
          let
             go :: Int# -> Word# -> State# d -> (# State# d, Int# #)
    go Int#
    _ Word#
    0## State# d
    s = (# State# d
    s, Int#
    1# #) -- no underflow
             go Int#
    i Word#
    y   State# d
    s
                | Int# -> Bool
    isTrue# (Int#
    i Int# -> Int# -> Int#
    >=# Int#
    sz) = (# State# d
    s, Int#
    0# #) -- underflow
                | Bool
    True = case MutableWordArray# d -> Int# -> State# d -> (# State# d, Word# #)
    forall d.
    MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
    readWordArray# MutableWordArray# d
    mwa Int#
    i State# d
    s of
                   (# State# d
    s1, Word#
    x #) -> let !(# Word#
    l,Int#
    h #) = Word# -> Word# -> (# Word#, Int# #)
    subWordC# Word#
    x Word#
    y
                      in case MutableWordArray# d -> Int# -> Word# -> State# d -> State# d
    forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# d
    mwa Int#
    i Word#
    l State# d
    s1 of
                         State# d
    s2 -> Int# -> Word# -> State# d -> (# State# d, Int# #)
    go (Int#
    i Int# -> Int# -> Int#
    +# Int#
    1#) (Int# -> Word#
    int2Word# Int#
    h) State# d
    s2
          in Int# -> Word# -> State# d -> (# State# d, Int# #)
    go Int#
    ii Word#
    iw State# d
    is

    -- | Trim `a` of `k` less significant limbs and then compare the result with `b`
    --
    -- "mwa" doesn't need to be trimmed
    mwaTrimCompare :: Int# -> MutableWordArray# s -> WordArray# -> State# s -> (# State# s, Ordering #)
    mwaTrimCompare :: forall s.
    Int#
    -> MutableWordArray# s
    -> WordArray#
    -> State# s
    -> (# State# s, Ordering #)
    mwaTrimCompare Int#
    k MutableWordArray# s
    mwa WordArray#
    wb State# s
    s1
       | (# State# s
    s, Int#
    szA #) <- MutableWordArray# s -> State# s -> (# State# s, Int# #)
    forall s. MutableWordArray# s -> State# s -> (# State# s, Int# #)
    mwaSize# MutableWordArray# s
    mwa State# s
    s1
       , Int#
    szB <- WordArray# -> Int#
    wordArraySize# WordArray#
    wb
       =
         let
          go :: Int# -> State# s -> (# State# s, Ordering #)
    go Int#
    i State# s
    s
             | Int# -> Bool
    isTrue# (Int#
    i Int# -> Int# -> Int#
    <# Int#
    0#) = (# State# s
    s, Ordering
    EQ #)
             | Bool
    True = case MutableWordArray# s -> Int# -> State# s -> (# State# s, Word# #)
    forall d.
    MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
    readWordArray# MutableWordArray# s
    mwa (Int#
    i Int# -> Int# -> Int#
    +# Int#
    k) State# s
    s of
                (# State# s
    s2, Word#
    ai #) ->
                   let bi :: Word#
    bi = if Int# -> Bool
    isTrue# (Int#
    i Int# -> Int# -> Int#
    >=# Int#
    szB)
                               then Word#
    0##
                               else WordArray# -> Int# -> Word#
    indexWordArray# WordArray#
    wb Int#
    i
                   in if | Int# -> Bool
    isTrue# (Word#
    ai Word# -> Word# -> Int#
    `gtWord#` Word#
    bi) -> (# State# s
    s2, Ordering
    GT #)
                         | Int# -> Bool
    isTrue# (Word#
    bi Word# -> Word# -> Int#
    `gtWord#` Word#
    ai) -> (# State# s
    s2, Ordering
    LT #)
                         | Bool
    True                      -> Int# -> State# s -> (# State# s, Ordering #)
    go (Int#
    i Int# -> Int# -> Int#
    -# Int#
    1#) State# s
    s2

          szTrimA :: Int#
    szTrimA = Int#
    szA Int# -> Int# -> Int#
    -# Int#
    k

         in if | Int# -> Bool
    isTrue# (Int#
    szTrimA Int# -> Int# -> Int#
    <# Int#
    szB) -> (# State# s
    s, Ordering
    LT #)
               | Bool
    True                     -> Int# -> State# s -> (# State# s, Ordering #)
    go (Int#
    szA Int# -> Int# -> Int#
    -# Int#
    k Int# -> Int# -> Int#
    -# Int#
    1#) State# s
    s

    -- | Sub array inplace (at the specified offset) in the mwa with carry propagation.
    --
    -- We don't trim the resulting array!
    --
    -- Return False# on underflow.
    mwaSubInplaceArray :: MutableWordArray# d -> Int# -> WordArray# -> State# d -> (# State# d, Bool# #)
    mwaSubInplaceArray :: forall d.
    MutableWordArray# d
    -> Int# -> WordArray# -> State# d -> (# State# d, Int# #)
    mwaSubInplaceArray MutableWordArray# d
    mwa Int#
    off WordArray#
    wb = Int# -> State# d -> (# State# d, Int# #)
    go (WordArray# -> Int#
    wordArraySize# WordArray#
    wb Int# -> Int# -> Int#
    -# Int#
    1#)
       where
          go :: Int# -> State# d -> (# State# d, Int# #)
    go Int#
    i State# d
    s
             | Int# -> Bool
    isTrue# (Int#
    i Int# -> Int# -> Int#
    <# Int#
    0#) = (# State# d
    s, Int#
    1# #) -- no underflow
             | Bool
    True
             = case MutableWordArray# d
    -> Int# -> Word# -> State# d -> (# State# d, Int# #)
    forall d.
    MutableWordArray# d
    -> Int# -> Word# -> State# d -> (# State# d, Int# #)
    mwaSubInplaceWord# MutableWordArray# d
    mwa (Int#
    off Int# -> Int# -> Int#
    +# Int#
    i) (WordArray# -> Int# -> Word#
    indexWordArray# WordArray#
    wb Int#
    i) State# d
    s of
                (# State# d
    s2, Int#
    1# #) -> Int# -> State# d -> (# State# d, Int# #)
    go (Int#
    i Int# -> Int# -> Int#
    -# Int#
    1#) State# d
    s2
                (# State# d
    s2, Int#
    _  #) -> (# State# d
    s2, Int#
    0# #) -- underflow

    -- | Add array inplace (a the specified offset) in the mwa with carry propagation.
    --
    -- Upper bound of the result mutable aray is not checked against overflow.
    mwaAddInplaceArray :: MutableWordArray# d -> Int# -> WordArray# -> State# d -> State# d
    mwaAddInplaceArray :: forall d.
    MutableWordArray# d -> Int# -> WordArray# -> State# d -> State# d
    mwaAddInplaceArray MutableWordArray# d
    mwa Int#
    off WordArray#
    wb = Int# -> Word# -> State# d -> State# d
    go Int#
    0# Word#
    0##
       where
          !maxi :: Int#
    maxi = WordArray# -> Int#
    wordArraySize# WordArray#
    wb
          go :: Int# -> Word# -> State# d -> State# d
    go Int#
    i Word#
    c State# d
    s
             | Int# -> Bool
    isTrue# (Int#
    i Int# -> Int# -> Int#
    ==# Int#
    maxi) = MutableWordArray# d -> Int# -> Word# -> State# d -> State# d
    forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    mwaAddInplaceWord# MutableWordArray# d
    mwa (Int#
    i Int# -> Int# -> Int#
    +# Int#
    off) Word#
    c State# d
    s
             | Bool
    True
             = case MutableWordArray# d -> Int# -> State# d -> (# State# d, Word# #)
    forall d.
    MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
    readWordArray# MutableWordArray# d
    mwa (Int#
    i Int# -> Int# -> Int#
    +# Int#
    off) State# d
    s of
                (# State# d
    s, Word#
    v #) -> case Word# -> Word# -> Word# -> (# Word#, Word# #)
    plusWord3# Word#
    v (WordArray# -> Int# -> Word#
    indexWordArray# WordArray#
    wb Int#
    i) Word#
    c of
                   (# Word#
    c', Word#
    v' #) -> case MutableWordArray# d -> Int# -> Word# -> State# d -> State# d
    forall s.
    MutableWordArray# s -> Int# -> Word# -> State# s -> State# s
    writeWordArray# MutableWordArray# d
    mwa (Int#
    i Int# -> Int# -> Int#
    +# Int#
    off) Word#
    v' State# d
    s of
                      State# d
    s -> Int# -> Word# -> State# d -> State# d
    go (Int#
    i Int# -> Int# -> Int#
    +# Int#
    1#) Word#
    c' State# d
    s

    -- | Sub array inplace (at the specified offset) in the mwa with carry propagation.
    --
    -- We don't trim the resulting array!
    --
    -- Return False# on underflow.
    mwaSubInplaceMutableArray :: MutableWordArray# d -> Int# -> MutableWordArray# d -> State# d -> (# State# d, Bool# #)
    mwaSubInplaceMutableArray :: forall d.
    MutableWordArray# d
    -> Int# -> MutableWordArray# d -> State# d -> (# State# d, Int# #)
    mwaSubInplaceMutableArray MutableWordArray# d
    mwa Int#
    off MutableWordArray# d
    mwb State# d
    s0 =
       case MutableWordArray# d -> State# d -> (# State# d, Int# #)
    forall s. MutableWordArray# s -> State# s -> (# State# s, Int# #)
    mwaSize# MutableWordArray# d
    mwb State# d
    s0 of
          (# State# d
    s1, Int#
    szB #) -> Int# -> State# d -> (# State# d, Int# #)
    go (Int#
    szB Int# -> Int# -> Int#
    -# Int#
    1#) State# d
    s1
       where
          go :: Int# -> State# d -> (# State# d, Int# #)
    go Int#
    i State# d
    s
             | Int# -> Bool
    isTrue# (Int#
    i Int# -> Int# -> Int#
    <# Int#
    0#) = (# State# d
    s, Int#
    1# #) -- no underflow
             | Bool
    True
             = case MutableWordArray# d -> Int# -> State# d -> (# State# d, Word# #)
    forall d.
    MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
    readWordArray# MutableWordArray# d
    mwb Int#
    i State# d
    s of
                (# State# d
    s1, Word#
    bi #) -> case MutableWordArray# d
    -> Int# -> Word# -> State# d -> (# State# d, Int# #)
    forall d.
    MutableWordArray# d
    -> Int# -> Word# -> State# d -> (# State# d, Int# #)
    mwaSubInplaceWord# MutableWordArray# d
    mwa (Int#
    off Int# -> Int# -> Int#
    +# Int#
    i) Word#
    bi State# d
    s1 of
                   (# State# d
    s2, Int#
    1# #) -> Int# -> State# d -> (# State# d, Int# #)
    go (Int#
    i Int# -> Int# -> Int#
    -# Int#
    1#) State# d
    s2
                   (# State# d
    s2, Int#
    _  #) -> (# State# d
    s2, Int#
    0# #) -- underflow

    -- | Sub an array inplace and then trim zeroes
    --
    -- Don't check overflow. The caller must ensure that a>=b
    mwaSubInplaceArrayTrim :: MutableWordArray# d -> Int# -> WordArray# -> State# d -> State# d
    mwaSubInplaceArrayTrim :: forall d.
    MutableWordArray# d -> Int# -> WordArray# -> State# d -> State# d
    mwaSubInplaceArrayTrim MutableWordArray# d
    mwa Int#
    off WordArray#
    wb State# d
    s =
       case MutableWordArray# d
    -> Int# -> WordArray# -> State# d -> (# State# d, Int# #)
    forall d.
    MutableWordArray# d
    -> Int# -> WordArray# -> State# d -> (# State# d, Int# #)
    mwaSubInplaceArray MutableWordArray# d
    mwa Int#
    off WordArray#
    wb State# d
    s of
          (# State# d
    s', Int#
    _ #) -> MutableWordArray# d -> State# d -> State# d
    forall s. MutableByteArray# s -> State# s -> State# s
    mwaTrimZeroes# MutableWordArray# d
    mwa State# d
    s'

    -- | Read an indexed Word in the MutableWordArray. If the index is out-of-bound,
    -- return zero.
    mwaReadOrZero :: MutableWordArray# s -> Int# -> State# s  -> (# State# s, Word# #)
    mwaReadOrZero :: forall d.
    MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
    mwaReadOrZero MutableWordArray# s
    mwa Int#
    i State# s
    s = case MutableWordArray# s -> State# s -> (# State# s, Int# #)
    forall s. MutableWordArray# s -> State# s -> (# State# s, Int# #)
    mwaSize# MutableWordArray# s
    mwa State# s
    s of
       (# State# s
    s2, Int#
    sz #)
          | Int# -> Bool
    isTrue# (Int#
    i Int# -> Int# -> Int#
    >=# Int#
    sz) -> (# State# s
    s2, Word#
    0## #)
          | Int# -> Bool
    isTrue# (Int#
    i Int# -> Int# -> Int#
    <# Int#
    0#)  -> (# State# s
    s2, Word#
    0## #)
          | Bool
    True               -> MutableWordArray# s -> Int# -> State# s -> (# State# s, Word# #)
    forall d.
    MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
    readWordArray# MutableWordArray# s
    mwa Int#
    i State# s
    s2

    mwaRead# :: MutableWordArray# s -> Int# -> State# s -> (# State# s, Word# #)
    mwaRead# :: forall d.
    MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
    mwaRead# = MutableByteArray# s -> Int# -> State# s -> (# State# s, Word# #)
    forall d.
    MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
    readWordArray#