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

    -- | Multi-precision natural
    module GHC.Num.BigNat where

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

    import GHC.Prim
    import GHC.Types
    import GHC.Classes
    import GHC.Magic
    import GHC.Num.Primitives
    import GHC.Num.WordArray
    import GHC.Num.Backend

    #if WORD_SIZE_IN_BITS < 64
    import GHC.IntWord64
    #endif

    default ()

    -- | A BigNat
    --
    -- Represented as an array of limbs (Word#) stored in little-endian order (Word#
    -- themselves use machine order).
    --
    -- Invariant (canonical representation): higher Word# is non-zero.
    --
    -- As a consequence, zero is represented with a WordArray# whose size is 0.
    type BigNat# = WordArray#
       -- we use a type-alias instead of an unlifted newtype to make Integer/Natural
       -- types easier to wire in the compiler

    -- | A lifted BigNat
    --
    -- Represented as an array of limbs (Word#) stored in little-endian order (Word#
    -- themselves use machine order).
    --
    -- Invariant (canonical representation): higher Word# is non-zero.
    --
    -- As a consequence, zero is represented with a WordArray# whose size is 0.
    data BigNat = BN# { BigNat -> BigNat#
    unBigNat :: BigNat# }

    -- Note [Why Void#?]
    -- ~~~~~~~~~~~~~~~~~
    --
    -- We can't have top-level BigNat# for now because they are unlifted ByteArray#
    -- (see #17521). So we use functions that take an empty argument Void# that
    -- will be discarded at compile time.

    -- | Check that the BigNat is valid
    bigNatCheck# :: BigNat# -> Bool#
    bigNatCheck# :: BigNat# -> Bool#
    bigNatCheck# BigNat#
    bn
       | Bool#
    0#  <- BigNat# -> Bool#
    bigNatSize# BigNat#
    bn                         = Bool#
    1#
       -- check that size is a multiple of Word size
       | Bool#
    r <- Bool# -> Bool# -> Bool#
    remInt# (BigNat# -> Bool#
    sizeofByteArray# BigNat#
    bn) WORD_SIZE_IN_BYTES#
       , Bool# -> Bool
    isTrue# (Bool#
    r Bool# -> Bool# -> Bool#
    /=# Bool#
    0#)                            = Bool#
    0#
       -- check that most-significant limb isn't zero
       | Word#
    0## <- BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    bn (BigNat# -> Bool#
    bigNatSize# BigNat#
    bn Bool# -> Bool# -> Bool#
    -# Bool#
    1#) = Bool#
    0#
       | Bool
    True                                          = Bool#
    1#

    -- | Check that the BigNat is valid
    bigNatCheck :: BigNat# -> Bool
    bigNatCheck :: BigNat# -> Bool
    bigNatCheck BigNat#
    bn = Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    bigNatCheck# BigNat#
    bn)

    -- | Number of words in the BigNat
    bigNatSize :: BigNat# -> Word
    bigNatSize :: BigNat# -> Word
    bigNatSize BigNat#
    bn = Word# -> Word
    W# (Bool# -> Word#
    int2Word# (BigNat# -> Bool#
    bigNatSize# BigNat#
    bn))

    -- | Number of words in the BigNat
    bigNatSize# :: BigNat# -> Int#
    bigNatSize# :: BigNat# -> Bool#
    bigNatSize# BigNat#
    ba = BigNat# -> Bool#
    wordArraySize# BigNat#
    ba

    {-# NOINLINE bigNatZero #-}
    bigNatZero :: BigNat
    bigNatZero :: BigNat
    bigNatZero = BigNat# -> BigNat
    BN# (Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArray# Bool#
    0# (\MutableWordArray# RealWorld
    _ State# RealWorld
    s -> State# RealWorld
    s))

    {-# NOINLINE bigNatOne #-}
    bigNatOne :: BigNat
    bigNatOne :: BigNat
    bigNatOne = BigNat# -> BigNat
    BN# (Word# -> BigNat#
    bigNatFromWord# Word#
    1##)

    -- | BigNat Zero
    bigNatZero# :: Void# -> BigNat# -- cf Note [Why Void#?]
    bigNatZero# :: Void# -> BigNat#
    bigNatZero# Void#
    _ = case BigNat
    bigNatZero of
       BN# BigNat#
    w -> BigNat#
    w

    -- | BigNat one
    bigNatOne# :: Void# -> BigNat# -- cf Note [Why Void#?]
    bigNatOne# :: Void# -> BigNat#
    bigNatOne# Void#
    _ = case BigNat
    bigNatOne of
       BN# BigNat#
    w -> BigNat#
    w

    raiseDivZero_BigNat :: Void# -> BigNat#
    raiseDivZero_BigNat :: Void# -> BigNat#
    raiseDivZero_BigNat Void#
    _ = case Any
    forall a. a
    raiseDivZero of
       !Any
    _ -> Void# -> BigNat#
    bigNatZero# Void#
    void#
       -- see Note [ghc-bignum exceptions] in GHC.Num.Primitives

    -- | Indicate if a bigNat is zero
    bigNatIsZero :: BigNat# -> Bool
    bigNatIsZero :: BigNat# -> Bool
    bigNatIsZero BigNat#
    bn = Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    bigNatIsZero# BigNat#
    bn)

    -- | Indicate if a bigNat is zero
    bigNatIsZero# :: BigNat# -> Bool#
    bigNatIsZero# :: BigNat# -> Bool#
    bigNatIsZero# BigNat#
    ba = BigNat# -> Bool#
    wordArraySize# BigNat#
    ba Bool# -> Bool# -> Bool#
    ==# Bool#
    0#

    -- | Indicate if a bigNat is one
    bigNatIsOne :: BigNat# -> Bool
    bigNatIsOne :: BigNat# -> Bool
    bigNatIsOne BigNat#
    bn = Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    bigNatIsOne# BigNat#
    bn)

    -- | Indicate if a bigNat is one
    bigNatIsOne# :: BigNat# -> Bool#
    bigNatIsOne# :: BigNat# -> Bool#
    bigNatIsOne# BigNat#
    ba =
       BigNat# -> Bool#
    wordArraySize# BigNat#
    ba Bool# -> Bool# -> Bool#
    ==# Bool#
    1#
       Bool# -> Bool# -> Bool#
    &&# BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    ba Bool#
    0# Word# -> Word# -> Bool#
    `eqWord#` Word#
    1##

    -- | Indicate if a bigNat is two
    bigNatIsTwo :: BigNat# -> Bool
    bigNatIsTwo :: BigNat# -> Bool
    bigNatIsTwo BigNat#
    bn = Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    bigNatIsTwo# BigNat#
    bn)

    -- | Indicate if a bigNat is two
    bigNatIsTwo# :: BigNat# -> Bool#
    bigNatIsTwo# :: BigNat# -> Bool#
    bigNatIsTwo# BigNat#
    ba =
       BigNat# -> Bool#
    wordArraySize# BigNat#
    ba Bool# -> Bool# -> Bool#
    ==# Bool#
    1#
       Bool# -> Bool# -> Bool#
    &&# BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    ba Bool#
    0# Word# -> Word# -> Bool#
    `eqWord#` Word#
    2##

    -- | Indicate if the value is a power of two and which one
    bigNatIsPowerOf2# :: BigNat# -> (# (# #) | Word# #)
    bigNatIsPowerOf2# :: BigNat# -> (# (# #) | Word# #)
    bigNatIsPowerOf2# BigNat#
    a
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a                      = (# (# #) | #)
       | Bool
    True = case Word# -> (# (# #) | Word# #)
    wordIsPowerOf2# Word#
    msw of
                   (# (# #) | #) -> (# (# #) | #)
                   (# | Word#
    c  #) -> case Bool# -> Bool#
    checkAllZeroes (Bool#
    imax Bool# -> Bool# -> Bool#
    -# Bool#
    1#) of
                      Bool#
    0# -> (# (# #) | #)
                      Bool#
    _  -> (# | Word#
    c Word# -> Word# -> Word#
    `plusWord#`
                                  (Bool# -> Word#
    int2Word# Bool#
    imax Word# -> Bool# -> Word#
    `uncheckedShiftL#` WORD_SIZE_BITS_SHIFT#) #)
       where
          msw :: Word#
    msw  = BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    a Bool#
    imax
          sz :: Bool#
    sz   = BigNat# -> Bool#
    bigNatSize# BigNat#
    a
          imax :: Bool#
    imax = Bool#
    sz Bool# -> Bool# -> Bool#
    -# Bool#
    1#
          checkAllZeroes :: Bool# -> Bool#
    checkAllZeroes Bool#
    i
             | Bool# -> Bool
    isTrue# (Bool#
    i Bool# -> Bool# -> Bool#
    <# Bool#
    0#) = Bool#
    1#
             | Bool
    True = case BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    a Bool#
    i of
                         Word#
    0## -> Bool# -> Bool#
    checkAllZeroes (Bool#
    i Bool# -> Bool# -> Bool#
    -# Bool#
    1#)
                         Word#
    _   -> Bool#
    0#

    -- | Return the Word# at the given index
    bigNatIndex# :: BigNat# -> Int# -> Word#
    bigNatIndex# :: BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    x Bool#
    i = BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    x Bool#
    i

    -- | Return the Word# at the given index
    bigNatIndex :: BigNat# -> Int# -> Word
    bigNatIndex :: BigNat# -> Bool# -> Word
    bigNatIndex BigNat#
    bn Bool#
    i = Word# -> Word
    W# (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    bn Bool#
    i)

    -------------------------------------------------
    -- Conversion
    -------------------------------------------------

    -- | Create a BigNat from a Word
    bigNatFromWord :: Word -> BigNat#
    bigNatFromWord :: Word -> BigNat#
    bigNatFromWord (W# Word#
    w) = Word# -> BigNat#
    bigNatFromWord# Word#
    w

    -- | Create a BigNat from a Word
    bigNatFromWord# :: Word# -> BigNat#
    bigNatFromWord# :: Word# -> BigNat#
    bigNatFromWord# Word#
    0## = Void# -> BigNat#
    bigNatZero# Void#
    void#
    bigNatFromWord# Word#
    w   = Word# -> BigNat#
    wordArrayFromWord# Word#
    w

    -- | Convert a list of non-zero Words (most-significant first) into a BigNat
    bigNatFromWordList :: [Word] -> BigNat#
    bigNatFromWordList :: [Word] -> BigNat#
    bigNatFromWordList (W# Word#
    0##:[Word]
    xs) = [Word] -> BigNat#
    bigNatFromWordList [Word]
    xs
    bigNatFromWordList [Word]
    xs          = [Word] -> BigNat#
    bigNatFromWordListUnsafe [Word]
    xs

    -- | Convert a list of non-zero Words (most-significant first) into a BigNat
    bigNatFromWordList# :: [Word] -> WordArray#
    {-# NOINLINE bigNatFromWordList# #-}
    bigNatFromWordList# :: [Word] -> BigNat#
    bigNatFromWordList# [Word]
    xs = [Word] -> BigNat#
    bigNatFromWordList [Word]
    xs

    -- | Return the absolute value of the Int# in a BigNat
    bigNatFromAbsInt# :: Int# -> BigNat#
    bigNatFromAbsInt# :: Bool# -> BigNat#
    bigNatFromAbsInt# Bool#
    i = Word# -> BigNat#
    bigNatFromWord# (Bool# -> Word#
    wordFromAbsInt# Bool#
    i)

    -- | Convert a list of non-zero Words (most-significant first) into a BigNat.
    -- Don't remove most-significant zero words
    bigNatFromWordListUnsafe :: [Word] -> BigNat#
    bigNatFromWordListUnsafe :: [Word] -> BigNat#
    bigNatFromWordListUnsafe [] = Void# -> BigNat#
    bigNatZero# Void#
    void#
    bigNatFromWordListUnsafe [Word]
    xs =
       let
          length :: Bool# -> [a] -> Bool#
    length Bool#
    i []     = Bool#
    i
          length Bool#
    i (a
    _:[a]
    ys) = Bool# -> [a] -> Bool#
    length (Bool#
    i Bool# -> Bool# -> Bool#
    +# Bool#
    1#) [a]
    ys
          !lxs :: Bool#
    lxs = Bool# -> [Word] -> Bool#
    forall {a}. Bool# -> [a] -> Bool#
    length Bool#
    0# [Word]
    xs
          writeWordList :: MutableWordArray# s -> Bool# -> [Word] -> State# s -> State# s
    writeWordList MutableWordArray# s
    _mwa Bool#
    _i []        State# s
    s = State# s
    s
          writeWordList MutableWordArray# s
    mwa   Bool#
    i (W# Word#
    w:[Word]
    ws) State# s
    s =
             case MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# s
    mwa Bool#
    i Word#
    w State# s
    s of
                State# s
    s1 -> MutableWordArray# s -> Bool# -> [Word] -> State# s -> State# s
    writeWordList MutableWordArray# s
    mwa (Bool#
    i Bool# -> Bool# -> Bool#
    -# Bool#
    1#) [Word]
    ws State# s
    s1
       in Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArray# Bool#
    lxs \MutableWordArray# RealWorld
    mwa ->
                MutableWordArray# RealWorld
    -> Bool# -> [Word] -> State# RealWorld -> State# RealWorld
    forall {s}.
    MutableWordArray# s -> Bool# -> [Word] -> State# s -> State# s
    writeWordList MutableWordArray# RealWorld
    mwa (Bool#
    lxs Bool# -> Bool# -> Bool#
    -# Bool#
    1#) [Word]
    xs

    -- | Convert a BigNat into a list of non-zero Words (most-significant first)
    bigNatToWordList :: BigNat# -> [Word]
    bigNatToWordList :: BigNat# -> [Word]
    bigNatToWordList BigNat#
    bn = Bool# -> [Word]
    go (BigNat# -> Bool#
    bigNatSize# BigNat#
    bn)
       where
          go :: Bool# -> [Word]
    go Bool#
    0# = []
          go Bool#
    n  = BigNat# -> Bool# -> Word
    bigNatIndex BigNat#
    bn (Bool#
    n Bool# -> Bool# -> Bool#
    -# Bool#
    1#) Word -> [Word] -> [Word]
    forall a. a -> [a] -> [a]
    : Bool# -> [Word]
    go (Bool#
    n Bool# -> Bool# -> Bool#
    -# Bool#
    1#)

    -- | Convert two Word# (most-significant first) into a BigNat
    bigNatFromWord2# :: Word# -> Word# -> BigNat#
    bigNatFromWord2# :: Word# -> Word# -> BigNat#
    bigNatFromWord2# Word#
    0## Word#
    0## = Void# -> BigNat#
    bigNatZero# Void#
    void#
    bigNatFromWord2# Word#
    0## Word#
    l   = Word# -> BigNat#
    bigNatFromWord# Word#
    l
    bigNatFromWord2# Word#
    h   Word#
    l   = Word# -> Word# -> BigNat#
    wordArrayFromWord2# Word#
    h Word#
    l

    -- | Convert a BigNat into a Word#
    bigNatToWord# :: BigNat# -> Word#
    bigNatToWord# :: BigNat# -> Word#
    bigNatToWord# BigNat#
    a
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = Word#
    0##
       | Bool
    True           = BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    a Bool#
    0#

    -- | Convert a BigNat into a Word# if it fits
    bigNatToWordMaybe# :: BigNat# -> (# (# #) | Word# #)
    bigNatToWordMaybe# :: BigNat# -> (# (# #) | Word# #)
    bigNatToWordMaybe# BigNat#
    a
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a                = (#       | Word#
    0## #)
       | Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    bigNatSize# BigNat#
    a Bool# -> Bool# -> Bool#
    ># Bool#
    1#) = (# (# #) |     #)
       | Bool
    True                          = (#       | BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    a Bool#
    0# #)

    -- | Convert a BigNat into a Word
    bigNatToWord :: BigNat# -> Word
    bigNatToWord :: BigNat# -> Word
    bigNatToWord BigNat#
    bn = Word# -> Word
    W# (BigNat# -> Word#
    bigNatToWord# BigNat#
    bn)

    -- | Convert a BigNat into a Int#
    bigNatToInt# :: BigNat# -> Int#
    bigNatToInt# :: BigNat# -> Bool#
    bigNatToInt# BigNat#
    a
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = Bool#
    0#
       | Bool
    True           = BigNat# -> Bool# -> Bool#
    indexIntArray# BigNat#
    a Bool#
    0#

    -- | Convert a BigNat into a Int
    bigNatToInt :: BigNat# -> Int
    bigNatToInt :: BigNat# -> Int
    bigNatToInt BigNat#
    bn = Bool# -> Int
    I# (BigNat# -> Bool#
    bigNatToInt# BigNat#
    bn)

    #if WORD_SIZE_IN_BITS == 32

    -- | Convert a Word64# into a BigNat on 32-bit architectures
    bigNatFromWord64# :: Word64# -> BigNat#
    bigNatFromWord64# w64 = bigNatFromWord2# wh# wl#
      where
        wh# = word64ToWord# (uncheckedShiftRL64# w64 32#)
        wl# = word64ToWord# w64

    -- | Convert a BigNat into a Word64# on 32-bit architectures
    bigNatToWord64# :: BigNat# -> Word64#
    bigNatToWord64# b
      | bigNatIsZero b = wordToWord64# 0##
      | wl <- wordToWord64# (bigNatToWord# b)
      = if isTrue# (bigNatSize# b ># 1#)
          then
             let wh = wordToWord64# (bigNatIndex# b 1#)
             in uncheckedShiftL64# wh 32# `or64#` wl
          else wl

    #endif

    -- | Encode (# BigNat mantissa, Int# exponent #) into a Double#
    bigNatEncodeDouble# :: BigNat# -> Int# -> Double#
    bigNatEncodeDouble# :: BigNat# -> Bool# -> Double#
    bigNatEncodeDouble# BigNat#
    a Bool#
    e
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a
       = Word# -> Double#
    word2Double# Word#
    0## -- FIXME: isn't it NaN on 0# exponent?

       | Bool
    True
       = (BigNat# -> Bool# -> Double#) -> BigNat# -> Bool# -> Double#
    forall a. a -> a
    inline BigNat# -> Bool# -> Double#
    bignat_encode_double BigNat#
    a Bool#
    e

    -------------------------------------------------
    -- Predicates
    -------------------------------------------------

    -- | Test if a BigNat is greater than a Word
    bigNatGtWord# :: BigNat# -> Word# -> Bool#
    bigNatGtWord# :: BigNat# -> Word# -> Bool#
    bigNatGtWord# BigNat#
    bn Word#
    w =
       Bool# -> Bool#
    notB# (BigNat# -> Bool#
    bigNatIsZero# BigNat#
    bn)
       Bool# -> Bool# -> Bool#
    &&# (   BigNat# -> Bool#
    bigNatSize# BigNat#
    bn Bool# -> Bool# -> Bool#
    ># Bool#
    1#
           Bool# -> Bool# -> Bool#
    ||# BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    bn Bool#
    0# Word# -> Word# -> Bool#
    `gtWord#` Word#
    w
           )

    -- | Test if a BigNat is equal to a Word
    bigNatEqWord# :: BigNat# -> Word# -> Bool#
    bigNatEqWord# :: BigNat# -> Word# -> Bool#
    bigNatEqWord# BigNat#
    bn Word#
    w
       | Word#
    0## <- Word#
    w
       = BigNat# -> Bool#
    bigNatIsZero# BigNat#
    bn

       | Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    bigNatSize# BigNat#
    bn Bool# -> Bool# -> Bool#
    ==# Bool#
    1#)
       = BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    bn Bool#
    0# Word# -> Word# -> Bool#
    `eqWord#` Word#
    w

       | Bool
    True
       = Bool#
    0#

    -- | Test if a BigNat is greater than a Word
    bigNatGtWord :: BigNat# -> Word -> Bool
    bigNatGtWord :: BigNat# -> Word -> Bool
    bigNatGtWord BigNat#
    bn (W# Word#
    w) = Bool# -> Bool
    isTrue# (BigNat# -> Word# -> Bool#
    bigNatGtWord# BigNat#
    bn Word#
    w)

    -- | Test if a BigNat is lower than or equal to a Word
    bigNatLeWord# :: BigNat# -> Word# -> Bool#
    bigNatLeWord# :: BigNat# -> Word# -> Bool#
    bigNatLeWord# BigNat#
    bn Word#
    w = Bool# -> Bool#
    notB# (BigNat# -> Word# -> Bool#
    bigNatGtWord# BigNat#
    bn Word#
    w)

    -- | Test if a BigNat is lower than or equal to a Word
    bigNatLeWord :: BigNat# -> Word -> Bool
    bigNatLeWord :: BigNat# -> Word -> Bool
    bigNatLeWord BigNat#
    bn (W# Word#
    w) = Bool# -> Bool
    isTrue# (BigNat# -> Word# -> Bool#
    bigNatLeWord# BigNat#
    bn Word#
    w)

    -- | Equality test for BigNat
    bigNatEq# :: BigNat# -> BigNat# -> Bool#
    bigNatEq# :: BigNat# -> BigNat# -> Bool#
    bigNatEq# BigNat#
    wa BigNat#
    wb
       | Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    wordArraySize# BigNat#
    wa Bool# -> Bool# -> Bool#
    /=# BigNat# -> Bool#
    wordArraySize# BigNat#
    wb) = Bool#
    0#
       | Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    wordArraySize# BigNat#
    wa Bool# -> Bool# -> Bool#
    ==# Bool#
    0#)                = Bool#
    1#
       | Bool
    True = (BigNat# -> BigNat# -> Bool#) -> BigNat# -> BigNat# -> Bool#
    forall a. a -> a
    inline BigNat# -> BigNat# -> Bool#
    bignat_compare BigNat#
    wa BigNat#
    wb Bool# -> Bool# -> Bool#
    ==# Bool#
    0#

    -- | Equality test for BigNat
    bigNatEq :: BigNat# -> BigNat# -> Bool
    bigNatEq :: BigNat# -> BigNat# -> Bool
    bigNatEq BigNat#
    a BigNat#
    b = Bool# -> Bool
    isTrue# (BigNat# -> BigNat# -> Bool#
    bigNatEq# BigNat#
    a BigNat#
    b)

    -- | Inequality test for BigNat
    bigNatNe# :: BigNat# -> BigNat# -> Bool#
    bigNatNe# :: BigNat# -> BigNat# -> Bool#
    bigNatNe# BigNat#
    a BigNat#
    b = Bool# -> Bool#
    notB# (BigNat# -> BigNat# -> Bool#
    bigNatEq# BigNat#
    a BigNat#
    b)

    -- | Equality test for BigNat
    bigNatNe :: BigNat# -> BigNat# -> Bool
    bigNatNe :: BigNat# -> BigNat# -> Bool
    bigNatNe BigNat#
    a BigNat#
    b = Bool# -> Bool
    isTrue# (BigNat# -> BigNat# -> Bool#
    bigNatNe# BigNat#
    a BigNat#
    b)

    -- | Compare a BigNat and a Word#
    bigNatCompareWord# :: BigNat# -> Word# -> Ordering
    bigNatCompareWord# :: BigNat# -> Word# -> Ordering
    bigNatCompareWord# BigNat#
    a Word#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a                   = Word# -> Word# -> Ordering
    cmpW# Word#
    0## Word#
    b
       | Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    wordArraySize# BigNat#
    a Bool# -> Bool# -> Bool#
    ># Bool#
    1#) = Ordering
    GT
       | Bool
    True
       = Word# -> Word# -> Ordering
    cmpW# (BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a Bool#
    0#) Word#
    b

    -- | Compare a BigNat and a Word
    bigNatCompareWord :: BigNat# -> Word -> Ordering
    bigNatCompareWord :: BigNat# -> Word -> Ordering
    bigNatCompareWord BigNat#
    a (W# Word#
    b) = BigNat# -> Word# -> Ordering
    bigNatCompareWord# BigNat#
    a Word#
    b

    -- | Compare two BigNat
    bigNatCompare :: BigNat# -> BigNat# -> Ordering
    bigNatCompare :: BigNat# -> BigNat# -> Ordering
    bigNatCompare BigNat#
    a BigNat#
    b =
       let
          szA :: Bool#
    szA = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          szB :: Bool#
    szB = BigNat# -> Bool#
    wordArraySize# BigNat#
    b
       in if
       | Bool# -> Bool
    isTrue# (Bool#
    szA Bool# -> Bool# -> Bool#
    ># Bool#
    szB) -> Ordering
    GT
       | Bool# -> Bool
    isTrue# (Bool#
    szA Bool# -> Bool# -> Bool#
    <# Bool#
    szB) -> Ordering
    LT
       | Bool# -> Bool
    isTrue# (Bool#
    szA Bool# -> Bool# -> Bool#
    ==# Bool#
    0#) -> Ordering
    EQ
       | Bool
    True                 -> Bool# -> Bool# -> Ordering
    compareInt# ((BigNat# -> BigNat# -> Bool#) -> BigNat# -> BigNat# -> Bool#
    forall a. a -> a
    inline BigNat# -> BigNat# -> Bool#
    bignat_compare BigNat#
    a BigNat#
    b) Bool#
    0#

    -- | Predicate: a < b
    bigNatLt# :: BigNat# -> BigNat# -> Bool#
    bigNatLt# :: BigNat# -> BigNat# -> Bool#
    bigNatLt# BigNat#
    a BigNat#
    b
      | Ordering
    LT <- BigNat# -> BigNat# -> Ordering
    bigNatCompare BigNat#
    a BigNat#
    b = Bool#
    1#
      | Bool
    True                    = Bool#
    0#

    -- | Predicate: a < b
    bigNatLt :: BigNat# -> BigNat# -> Bool
    bigNatLt :: BigNat# -> BigNat# -> Bool
    bigNatLt BigNat#
    a BigNat#
    b = Bool# -> Bool
    isTrue# (BigNat# -> BigNat# -> Bool#
    bigNatLt# BigNat#
    a BigNat#
    b)

    -- | Predicate: a <= b
    bigNatLe# :: BigNat# -> BigNat# -> Bool#
    bigNatLe# :: BigNat# -> BigNat# -> Bool#
    bigNatLe# BigNat#
    a BigNat#
    b
      | Ordering
    GT <- BigNat# -> BigNat# -> Ordering
    bigNatCompare BigNat#
    a BigNat#
    b = Bool#
    0#
      | Bool
    True                    = Bool#
    1#

    -- | Predicate: a <= b
    bigNatLe :: BigNat# -> BigNat# -> Bool
    bigNatLe :: BigNat# -> BigNat# -> Bool
    bigNatLe BigNat#
    a BigNat#
    b = Bool# -> Bool
    isTrue# (BigNat# -> BigNat# -> Bool#
    bigNatLe# BigNat#
    a BigNat#
    b)

    -- | Predicate: a > b
    bigNatGt# :: BigNat# -> BigNat# -> Bool#
    bigNatGt# :: BigNat# -> BigNat# -> Bool#
    bigNatGt# BigNat#
    a BigNat#
    b
      | Ordering
    GT <- BigNat# -> BigNat# -> Ordering
    bigNatCompare BigNat#
    a BigNat#
    b = Bool#
    1#
      | Bool
    True                    = Bool#
    0#

    -- | Predicate: a > b
    bigNatGt :: BigNat# -> BigNat# -> Bool
    bigNatGt :: BigNat# -> BigNat# -> Bool
    bigNatGt BigNat#
    a BigNat#
    b = Bool# -> Bool
    isTrue# (BigNat# -> BigNat# -> Bool#
    bigNatGt# BigNat#
    a BigNat#
    b)

    -- | Predicate: a >= b
    bigNatGe# :: BigNat# -> BigNat# -> Bool#
    bigNatGe# :: BigNat# -> BigNat# -> Bool#
    bigNatGe# BigNat#
    a BigNat#
    b
      | Ordering
    LT <- BigNat# -> BigNat# -> Ordering
    bigNatCompare BigNat#
    a BigNat#
    b = Bool#
    0#
      | Bool
    True                    = Bool#
    1#

    -- | Predicate: a >= b
    bigNatGe :: BigNat# -> BigNat# -> Bool
    bigNatGe :: BigNat# -> BigNat# -> Bool
    bigNatGe BigNat#
    a BigNat#
    b = Bool# -> Bool
    isTrue# (BigNat# -> BigNat# -> Bool#
    bigNatGe# BigNat#
    a BigNat#
    b)

    -------------------------------------------------
    -- Addition
    -------------------------------------------------

    -- | Add a bigNat and a Word#
    bigNatAddWord# :: BigNat# -> Word# -> BigNat#
    bigNatAddWord# :: BigNat# -> Word# -> BigNat#
    bigNatAddWord# BigNat#
    a Word#
    b
       | Word#
    0## <- Word#
    b
       = BigNat#
    a

       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a
       = Word# -> BigNat#
    bigNatFromWord# Word#
    b

       | Bool
    True
       = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# (BigNat# -> Bool#
    wordArraySize# BigNat#
    a Bool# -> Bool# -> Bool#
    +# Bool#
    1#) \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
             (MutableWordArray# RealWorld
     -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> Word#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld
    bignat_add_word MutableWordArray# RealWorld
    mwa BigNat#
    a Word#
    b State# RealWorld
    s

    -- | Add a bigNat and a Word
    bigNatAddWord :: BigNat# -> Word -> BigNat#
    bigNatAddWord :: BigNat# -> Word -> BigNat#
    bigNatAddWord BigNat#
    a (W# Word#
    b) = BigNat# -> Word# -> BigNat#
    bigNatAddWord# BigNat#
    a Word#
    b

    -- | Add two bigNats
    bigNatAdd :: BigNat# -> BigNat# -> BigNat#
    bigNatAdd :: BigNat# -> BigNat# -> BigNat#
    bigNatAdd BigNat#
    a BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b = BigNat#
    a
       | Bool
    True =
       let
          !szA :: Bool#
    szA     = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          !szB :: Bool#
    szB     = BigNat# -> Bool#
    wordArraySize# BigNat#
    b
          !szMax :: Bool#
    szMax   = Bool# -> Bool# -> Bool#
    maxI# Bool#
    szA Bool#
    szB
          !sz :: Bool#
    sz      = Bool#
    szMax Bool# -> Bool# -> Bool#
    +# Bool#
    1# -- for the potential carry
       in Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# Bool#
    sz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
             (MutableWordArray# RealWorld
     -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
    bignat_add MutableWordArray# RealWorld
    mwa BigNat#
    a BigNat#
    b State# RealWorld
    s

    -------------------------------------------------
    -- Multiplication
    -------------------------------------------------

    -- | Multiply a BigNat by a Word#
    bigNatMulWord# :: BigNat# -> Word# -> BigNat#
    bigNatMulWord# :: BigNat# -> Word# -> BigNat#
    bigNatMulWord# BigNat#
    a Word#
    w
       | Word#
    0## <- Word#
    w       = Void# -> BigNat#
    bigNatZero# Void#
    void#
       | Word#
    1## <- Word#
    w       = BigNat#
    a
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = Void# -> BigNat#
    bigNatZero# Void#
    void#
       | BigNat# -> Bool
    bigNatIsOne  BigNat#
    a = Word# -> BigNat#
    bigNatFromWord# Word#
    w
       | Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    bigNatSize# BigNat#
    a Bool# -> Bool# -> Bool#
    ==# Bool#
    1#)
       = case Word# -> Word# -> (# Word#, Word# #)
    timesWord2# (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    a Bool#
    0#) Word#
    w of
          (# Word#
    h, Word#
    l #) -> Word# -> Word# -> BigNat#
    bigNatFromWord2# Word#
    h Word#
    l
       | Bool
    True = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# (BigNat# -> Bool#
    bigNatSize# BigNat#
    a Bool# -> Bool# -> Bool#
    +# Bool#
    1#) \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                   (MutableWordArray# RealWorld
     -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> Word#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld
    bignat_mul_word MutableWordArray# RealWorld
    mwa BigNat#
    a Word#
    w State# RealWorld
    s

    -- | Multiply a BigNAt by a Word
    bigNatMulWord :: BigNat# -> Word -> BigNat#
    bigNatMulWord :: BigNat# -> Word -> BigNat#
    bigNatMulWord BigNat#
    a (W# Word#
    w) = BigNat# -> Word# -> BigNat#
    bigNatMulWord# BigNat#
    a Word#
    w

    -- | Square a BigNat
    bigNatSqr :: BigNat# -> BigNat#
    bigNatSqr :: BigNat# -> BigNat#
    bigNatSqr BigNat#
    a = BigNat# -> BigNat# -> BigNat#
    bigNatMul BigNat#
    a BigNat#
    a
       -- This can be replaced by a backend primitive in the future (e.g. to use
       -- GMP's mpn_sqr)

    -- | Multiplication (classical algorithm)
    bigNatMul :: BigNat# -> BigNat# -> BigNat#
    bigNatMul :: BigNat# -> BigNat# -> BigNat#
    bigNatMul BigNat#
    a BigNat#
    b
       | BigNat# -> Word
    bigNatSize BigNat#
    b Word -> Word -> Bool
    forall a. Ord a => a -> a -> Bool
    > BigNat# -> Word
    bigNatSize BigNat#
    a = BigNat# -> BigNat# -> BigNat#
    bigNatMul BigNat#
    b BigNat#
    a -- optimize loops
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = BigNat#
    a
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b = BigNat#
    b
       | BigNat# -> Bool
    bigNatIsOne  BigNat#
    a = BigNat#
    b
       | BigNat# -> Bool
    bigNatIsOne  BigNat#
    b = BigNat#
    a
       | Bool
    True =
          let
             !szA :: Bool#
    szA = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
             !szB :: Bool#
    szB = BigNat# -> Bool#
    wordArraySize# BigNat#
    b
             !sz :: Bool#
    sz  = Bool#
    szA Bool# -> Bool# -> Bool#
    +# Bool#
    szB
          in Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# Bool#
    sz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s->
                (MutableWordArray# RealWorld
     -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
    bignat_mul MutableWordArray# RealWorld
    mwa BigNat#
    a BigNat#
    b State# RealWorld
    s

    -------------------------------------------------
    -- Subtraction
    -------------------------------------------------

    -- | Subtract a Word# from a BigNat
    --
    -- The BigNat must be bigger than the Word#.
    bigNatSubWordUnsafe# :: BigNat# -> Word# -> BigNat#
    bigNatSubWordUnsafe# :: BigNat# -> Word# -> BigNat#
    bigNatSubWordUnsafe# BigNat#
    x Word#
    y
       | Word#
    0## <- Word#
    y = BigNat#
    x
       | Bool
    True     = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# Bool#
    sz \MutableWordArray# RealWorld
    mwa -> MutableWordArray# RealWorld
    -> Word# -> Bool# -> State# RealWorld -> State# RealWorld
    forall {s}.
    MutableByteArray# s -> Word# -> Bool# -> State# s -> State# s
    go MutableWordArray# RealWorld
    mwa Word#
    y Bool#
    0#
       where
          !sz :: Bool#
    sz = BigNat# -> Bool#
    wordArraySize# BigNat#
    x

          go :: MutableByteArray# s -> Word# -> Bool# -> State# s -> State# s
    go MutableByteArray# s
    mwa Word#
    carry Bool#
    i State# s
    s
             | Bool# -> Bool
    isTrue# (Bool#
    i Bool# -> Bool# -> Bool#
    >=# Bool#
    sz)
             = State# s
    s

             | Word#
    0## <- Word#
    carry
             = MutableByteArray# s
    -> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
    forall s.
    MutableByteArray# s
    -> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
    mwaArrayCopy# MutableByteArray# s
    mwa Bool#
    i BigNat#
    x Bool#
    i (Bool#
    sz Bool# -> Bool# -> Bool#
    -# Bool#
    i) State# s
    s

             | Bool
    True
             = case Word# -> Word# -> (# Word#, Bool# #)
    subWordC# (BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    x Bool#
    i) Word#
    carry of
                (# Word#
    l, Bool#
    c #) -> case MutableByteArray# s -> Bool# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    mwaWrite# MutableByteArray# s
    mwa Bool#
    i Word#
    l State# s
    s of
                                  State# s
    s1 -> MutableByteArray# s -> Word# -> Bool# -> State# s -> State# s
    go MutableByteArray# s
    mwa (Bool# -> Word#
    int2Word# Bool#
    c) (Bool#
    i Bool# -> Bool# -> Bool#
    +# Bool#
    1#) State# s
    s1

    -- | Subtract a Word# from a BigNat
    --
    -- The BigNat must be bigger than the Word#.
    bigNatSubWordUnsafe :: BigNat# -> Word -> BigNat#
    bigNatSubWordUnsafe :: BigNat# -> Word -> BigNat#
    bigNatSubWordUnsafe BigNat#
    x (W# Word#
    y) = BigNat# -> Word# -> BigNat#
    bigNatSubWordUnsafe# BigNat#
    x Word#
    y

    -- | Subtract a Word# from a BigNat
    bigNatSubWord# :: BigNat# -> Word# -> (# (# #) | BigNat# #)
    bigNatSubWord# :: BigNat# -> Word# -> (# (# #) | BigNat# #)
    bigNatSubWord# BigNat#
    a Word#
    b
       | Word#
    0## <- Word#
    b          = (# | BigNat#
    a #)
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a    = (# (# #) | #)
       | Bool
    True
       = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> (# State# RealWorld, Bool# #))
    -> (# (# #) | BigNat# #)
    withNewWordArrayTrimedMaybe# (BigNat# -> Bool#
    bigNatSize# BigNat#
    a) \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                (MutableWordArray# RealWorld
     -> BigNat#
     -> Word#
     -> State# RealWorld
     -> (# State# RealWorld, Bool# #))
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> Word#
    -> State# RealWorld
    -> (# State# RealWorld, Bool# #)
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat#
    -> Word#
    -> State# RealWorld
    -> (# State# RealWorld, Bool# #)
    bignat_sub_word MutableWordArray# RealWorld
    mwa BigNat#
    a Word#
    b State# RealWorld
    s

    -- | Subtract two BigNat (don't check if a >= b)
    bigNatSubUnsafe :: BigNat# -> BigNat# -> BigNat#
    bigNatSubUnsafe :: BigNat# -> BigNat# -> BigNat#
    bigNatSubUnsafe BigNat#
    a BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b = BigNat#
    a
       | Bool
    True =
          let szA :: Bool#
    szA = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          in Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# Bool#
    szA \MutableWordArray# RealWorld
    mwa State# RealWorld
    s->
                case (MutableWordArray# RealWorld
     -> BigNat#
     -> BigNat#
     -> State# RealWorld
     -> (# State# RealWorld, Bool# #))
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> (# State# RealWorld, Bool# #)
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> (# State# RealWorld, Bool# #)
    bignat_sub MutableWordArray# RealWorld
    mwa BigNat#
    a BigNat#
    b State# RealWorld
    s of
                   (# State# RealWorld
    s', Bool#
    1# #) -> State# RealWorld
    s'
                   (# State# RealWorld
    s', Bool#
    _  #) -> case Any
    forall a. a
    raiseUnderflow of
                                     !Any
    _ -> State# RealWorld
    s'
                                     -- see Note [ghc-bignum exceptions] in
                                     -- GHC.Num.Primitives

    -- | Subtract two BigNat
    bigNatSub :: BigNat# -> BigNat# -> (# (# #) | BigNat# #)
    bigNatSub :: BigNat# -> BigNat# -> (# (# #) | BigNat# #)
    bigNatSub BigNat#
    a BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b = (# | BigNat#
    a #)
       | Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    bigNatSize# BigNat#
    a Bool# -> Bool# -> Bool#
    <# BigNat# -> Bool#
    bigNatSize# BigNat#
    b)
       = (# (# #) | #)

       | Bool
    True
       = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> (# State# RealWorld, Bool# #))
    -> (# (# #) | BigNat# #)
    withNewWordArrayTrimedMaybe# (BigNat# -> Bool#
    bigNatSize# BigNat#
    a) \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                (MutableWordArray# RealWorld
     -> BigNat#
     -> BigNat#
     -> State# RealWorld
     -> (# State# RealWorld, Bool# #))
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> (# State# RealWorld, Bool# #)
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> (# State# RealWorld, Bool# #)
    bignat_sub MutableWordArray# RealWorld
    mwa BigNat#
    a BigNat#
    b State# RealWorld
    s

    -------------------------------------------------
    -- Division
    -------------------------------------------------

    -- | Divide a BigNat by a Word, return the quotient
    --
    -- Require:
    --    b /= 0
    bigNatQuotWord# :: BigNat# -> Word# -> BigNat#
    bigNatQuotWord# :: BigNat# -> Word# -> BigNat#
    bigNatQuotWord# BigNat#
    a Word#
    b
       | Word#
    1## <- Word#
    b = BigNat#
    a
       | Word#
    0## <- Word#
    b = Void# -> BigNat#
    raiseDivZero_BigNat Void#
    void#
       | Bool
    True =
       let
          sz :: Bool#
    sz = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
       in Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# Bool#
    sz \MutableWordArray# RealWorld
    mwq State# RealWorld
    s ->
             (MutableWordArray# RealWorld
     -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> Word#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld
    bignat_quot_word MutableWordArray# RealWorld
    mwq BigNat#
    a Word#
    b State# RealWorld
    s

    -- | Divide a BigNat by a Word, return the quotient
    --
    -- Require:
    --    b /= 0
    bigNatQuotWord :: BigNat# -> Word -> BigNat#
    bigNatQuotWord :: BigNat# -> Word -> BigNat#
    bigNatQuotWord BigNat#
    a (W# Word#
    b) = BigNat# -> Word# -> BigNat#
    bigNatQuotWord# BigNat#
    a Word#
    b

    -- | Divide a BigNat by a Word, return the remainder
    --
    -- Require:
    --    b /= 0
    bigNatRemWord# :: BigNat# -> Word# -> Word#
    bigNatRemWord# :: BigNat# -> Word# -> Word#
    bigNatRemWord# BigNat#
    a Word#
    b
       | Word#
    0## <- Word#
    b       = Void# -> Word#
    raiseDivZero_Word# Void#
    void#
       | Word#
    1## <- Word#
    b       = Word#
    0##
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = Word#
    0##
       | Bool
    True           = (BigNat# -> Word# -> Word#) -> BigNat# -> Word# -> Word#
    forall a. a -> a
    inline BigNat# -> Word# -> Word#
    bignat_rem_word BigNat#
    a Word#
    b

    -- | Divide a BigNat by a Word, return the remainder
    --
    -- Require:
    --    b /= 0
    bigNatRemWord :: BigNat# -> Word -> Word
    bigNatRemWord :: BigNat# -> Word -> Word
    bigNatRemWord BigNat#
    a (W# Word#
    b) = Word# -> Word
    W# (BigNat# -> Word# -> Word#
    bigNatRemWord# BigNat#
    a Word#
    b)

    -- | QuotRem a BigNat by a Word
    --
    -- Require:
    --    b /= 0
    bigNatQuotRemWord# :: BigNat# -> Word# -> (# BigNat#, Word# #)
    bigNatQuotRemWord# :: BigNat# -> Word# -> (# BigNat#, Word# #)
    bigNatQuotRemWord# BigNat#
    a Word#
    b
       | Word#
    0## <- Word#
    b = case Any
    forall a. a
    raiseDivZero of
                      !Any
    _ -> (# Void# -> BigNat#
    bigNatZero# Void#
    void#, Word#
    0## #)
                      -- see Note [ghc-bignum exceptions] in GHC.Num.Primitives
       | Word#
    1## <- Word#
    b = (# BigNat#
    a, Word#
    0## #)
       | Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    bigNatSize# BigNat#
    a Bool# -> Bool# -> Bool#
    ==# Bool#
    1#)
       , Word#
    a0 <- BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a Bool#
    0#
       = case Word# -> Word# -> Ordering
    compareWord# Word#
    a0 Word#
    b of
          Ordering
    LT -> (# Void# -> BigNat#
    bigNatZero# Void#
    void#, Word#
    a0  #)
          Ordering
    EQ -> (# Void# -> BigNat#
    bigNatOne#  Void#
    void#, Word#
    0## #)
          Ordering
    GT -> case Word# -> Word# -> (# Word#, Word# #)
    quotRemWord# Word#
    a0 Word#
    b of
                   (# Word#
    q, Word#
    r #) -> (# Word# -> BigNat#
    bigNatFromWord# Word#
    q, Word#
    r #)
       | Bool
    True =
       let
          sz :: Bool#
    sz = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          io :: State# RealWorld -> (# State# RealWorld, (# BigNat#, Word# #) #)
    io State# RealWorld
    s =
             case Bool#
    -> State# RealWorld
    -> (# State# RealWorld, MutableWordArray# RealWorld #)
    forall s. Bool# -> State# s -> (# State# s, MutableWordArray# s #)
    newWordArray# Bool#
    sz State# RealWorld
    s of { (# State# RealWorld
    s1, MutableWordArray# RealWorld
    mwq #) ->
             case (MutableWordArray# RealWorld
     -> BigNat#
     -> Word#
     -> State# RealWorld
     -> (# State# RealWorld, Word# #))
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> Word#
    -> State# RealWorld
    -> (# State# RealWorld, Word# #)
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat#
    -> Word#
    -> State# RealWorld
    -> (# State# RealWorld, Word# #)
    bignat_quotrem_word MutableWordArray# RealWorld
    mwq BigNat#
    a Word#
    b State# RealWorld
    s1 of { (# State# RealWorld
    s2, Word#
    r #)  ->
             case MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld
    forall s. MutableByteArray# s -> State# s -> State# s
    mwaTrimZeroes# MutableWordArray# RealWorld
    mwq State# RealWorld
    s2 of { State# RealWorld
    s3 ->
             case MutableWordArray# RealWorld
    -> State# RealWorld -> (# State# RealWorld, BigNat# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, BigNat# #)
    unsafeFreezeByteArray# MutableWordArray# RealWorld
    mwq State# RealWorld
    s3 of { (# State# RealWorld
    s4, BigNat#
    wq #) ->
             (# State# RealWorld
    s4, (# BigNat#
    wq, Word#
    r #) #)
             }}}}
       in case (State# RealWorld -> (# State# RealWorld, (# BigNat#, Word# #) #))
    -> (# State# RealWorld, (# BigNat#, Word# #) #)
    forall o. (State# RealWorld -> o) -> o
    runRW# State# RealWorld -> (# State# RealWorld, (# BigNat#, Word# #) #)
    io of
             (# State# RealWorld
    _, (# BigNat#
    wq,Word#
    r #) #) -> (# BigNat#
    wq, Word#
    r #)

    -- | BigNat division returning (quotient,remainder)
    bigNatQuotRem# :: BigNat# -> BigNat# -> (# BigNat#, BigNat# #)
    bigNatQuotRem# :: BigNat# -> BigNat# -> (# BigNat#, BigNat# #)
    bigNatQuotRem# BigNat#
    a BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b          = case Any
    forall a. a
    raiseDivZero of
                                     !Any
    _ -> (# Void# -> BigNat#
    bigNatZero# Void#
    void#, Void# -> BigNat#
    bigNatZero# Void#
    void# #)
                                     -- see Note [ghc-bignum exceptions] in GHC.Num.Primitives
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a          = (# Void# -> BigNat#
    bigNatZero# Void#
    void#, Void# -> BigNat#
    bigNatZero# Void#
    void# #)
       | BigNat# -> Bool
    bigNatIsOne BigNat#
    b           = (# BigNat#
    a                , Void# -> BigNat#
    bigNatZero# Void#
    void# #)
       | Ordering
    LT <- Ordering
    cmp               = (# Void# -> BigNat#
    bigNatZero# Void#
    void#, BigNat#
    a #)
       | Ordering
    EQ <- Ordering
    cmp               = (# Void# -> BigNat#
    bigNatOne#  Void#
    void#, Void# -> BigNat#
    bigNatZero# Void#
    void# #)
       | Bool# -> Bool
    isTrue# (Bool#
    szB Bool# -> Bool# -> Bool#
    ==# Bool#
    1#)    = case BigNat# -> Word# -> (# BigNat#, Word# #)
    bigNatQuotRemWord# BigNat#
    a (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    b Bool#
    0#) of
                                     (# BigNat#
    q, Word#
    r #) -> (# BigNat#
    q, Word# -> BigNat#
    bigNatFromWord# Word#
    r #)

       | Bool
    True = Bool#
    -> Bool#
    -> (MutableWordArray# RealWorld
        -> MutableWordArray# RealWorld
        -> State# RealWorld
        -> State# RealWorld)
    -> (# BigNat#, BigNat# #)
    withNewWordArray2Trimed# Bool#
    szQ Bool#
    szR \MutableWordArray# RealWorld
    mwq MutableWordArray# RealWorld
    mwr State# RealWorld
    s ->
                         (MutableWordArray# RealWorld
     -> MutableWordArray# RealWorld
     -> BigNat#
     -> BigNat#
     -> State# RealWorld
     -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> State# RealWorld
    bignat_quotrem MutableWordArray# RealWorld
    mwq MutableWordArray# RealWorld
    mwr BigNat#
    a BigNat#
    b State# RealWorld
    s
       where
       cmp :: Ordering
    cmp = BigNat# -> BigNat# -> Ordering
    bigNatCompare BigNat#
    a BigNat#
    b
       szA :: Bool#
    szA = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
       szB :: Bool#
    szB = BigNat# -> Bool#
    wordArraySize# BigNat#
    b
       szQ :: Bool#
    szQ = Bool#
    1# Bool# -> Bool# -> Bool#
    +# Bool#
    szA Bool# -> Bool# -> Bool#
    -# Bool#
    szB
       szR :: Bool#
    szR = Bool#
    szB

    -- | BigNat division returning quotient
    bigNatQuot :: BigNat# -> BigNat# -> BigNat#
    bigNatQuot :: BigNat# -> BigNat# -> BigNat#
    bigNatQuot BigNat#
    a BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b          = Void# -> BigNat#
    raiseDivZero_BigNat Void#
    void#
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a          = Void# -> BigNat#
    bigNatZero# Void#
    void#
       | BigNat# -> Bool
    bigNatIsOne BigNat#
    b           = BigNat#
    a
       | Ordering
    LT <- Ordering
    cmp               = Void# -> BigNat#
    bigNatZero# Void#
    void#
       | Ordering
    EQ <- Ordering
    cmp               = Void# -> BigNat#
    bigNatOne# Void#
    void#
       | Bool# -> Bool
    isTrue# (Bool#
    szB Bool# -> Bool# -> Bool#
    ==# Bool#
    1#)    = BigNat# -> Word# -> BigNat#
    bigNatQuotWord# BigNat#
    a (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    b Bool#
    0#)
       | Bool
    True                    = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# Bool#
    szQ \MutableWordArray# RealWorld
    mwq State# RealWorld
    s ->
                                     (MutableWordArray# RealWorld
     -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
    bignat_quot MutableWordArray# RealWorld
    mwq BigNat#
    a BigNat#
    b State# RealWorld
    s
       where
       cmp :: Ordering
    cmp = BigNat# -> BigNat# -> Ordering
    bigNatCompare BigNat#
    a BigNat#
    b
       szA :: Bool#
    szA = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
       szB :: Bool#
    szB = BigNat# -> Bool#
    wordArraySize# BigNat#
    b
       szQ :: Bool#
    szQ = Bool#
    1# Bool# -> Bool# -> Bool#
    +# Bool#
    szA Bool# -> Bool# -> Bool#
    -# Bool#
    szB

    -- | BigNat division returning remainder
    bigNatRem :: BigNat# -> BigNat# -> BigNat#
    bigNatRem :: BigNat# -> BigNat# -> BigNat#
    bigNatRem BigNat#
    a BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b          = Void# -> BigNat#
    raiseDivZero_BigNat Void#
    void#
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a          = Void# -> BigNat#
    bigNatZero# Void#
    void#
       | BigNat# -> Bool
    bigNatIsOne BigNat#
    b           = Void# -> BigNat#
    bigNatZero# Void#
    void#
       | Ordering
    LT <- Ordering
    cmp               = BigNat#
    a
       | Ordering
    EQ <- Ordering
    cmp               = Void# -> BigNat#
    bigNatZero# Void#
    void#
       | Bool# -> Bool
    isTrue# (Bool#
    szB Bool# -> Bool# -> Bool#
    ==# Bool#
    1#)    = case BigNat# -> Word# -> Word#
    bigNatRemWord# BigNat#
    a (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    b Bool#
    0#) of
                                     Word#
    r -> Word# -> BigNat#
    bigNatFromWord# Word#
    r
       | Bool
    True                    = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# Bool#
    szR \MutableWordArray# RealWorld
    mwr State# RealWorld
    s ->
                                     (MutableWordArray# RealWorld
     -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
    bignat_rem MutableWordArray# RealWorld
    mwr BigNat#
    a BigNat#
    b State# RealWorld
    s
       where
       cmp :: Ordering
    cmp = BigNat# -> BigNat# -> Ordering
    bigNatCompare BigNat#
    a BigNat#
    b
       szB :: Bool#
    szB = BigNat# -> Bool#
    wordArraySize# BigNat#
    b
       szR :: Bool#
    szR = Bool#
    szB

    -------------------------------------------------
    -- GCD / LCM
    -------------------------------------------------

    -- Word#/Int# GCDs shouldn't be here in BigNat. However GMP provides a very fast
    -- implementation so we keep this here at least until we get a native Haskell
    -- implementation as fast as GMP's one. Note that these functions are used in
    -- `base` (e.g. in GHC.Real)

    -- | Greatest common divisor between two Word#
    gcdWord# :: Word# -> Word# -> Word#
    gcdWord# :: Word# -> Word# -> Word#
    gcdWord# = Word# -> Word# -> Word#
    bignat_gcd_word_word

    -- | Greatest common divisor between two Word
    gcdWord :: Word -> Word -> Word
    gcdWord :: Word -> Word -> Word
    gcdWord (W# Word#
    x) (W# Word#
    y) = Word# -> Word
    W# (Word# -> Word# -> Word#
    gcdWord# Word#
    x Word#
    y)

    -- | Greatest common divisor between two Int#
    --
    -- __Warning__: result may become negative if (at least) one argument
    -- is 'minBound'
    gcdInt# :: Int# -> Int# -> Int#
    gcdInt# :: Bool# -> Bool# -> Bool#
    gcdInt# Bool#
    x Bool#
    y = Word# -> Bool#
    word2Int# (Word# -> Word# -> Word#
    gcdWord# (Bool# -> Word#
    wordFromAbsInt# Bool#
    x) (Bool# -> Word#
    wordFromAbsInt# Bool#
    y))

    -- | Greatest common divisor between two Int
    --
    -- __Warning__: result may become negative if (at least) one argument
    -- is 'minBound'
    gcdInt :: Int -> Int -> Int
    gcdInt :: Int -> Int -> Int
    gcdInt (I# Bool#
    x) (I# Bool#
    y) = Bool# -> Int
    I# (Bool# -> Bool# -> Bool#
    gcdInt# Bool#
    x Bool#
    y)

    -- | Greatest common divisor
    bigNatGcd :: BigNat# -> BigNat# -> BigNat#
    bigNatGcd :: BigNat# -> BigNat# -> BigNat#
    bigNatGcd BigNat#
    a BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b = BigNat#
    a
       | BigNat# -> Bool
    bigNatIsOne BigNat#
    a  = BigNat#
    a
       | BigNat# -> Bool
    bigNatIsOne BigNat#
    b  = BigNat#
    b
       | Bool
    True
       = case (# BigNat# -> Bool#
    bigNatSize# BigNat#
    a, BigNat# -> Bool#
    bigNatSize# BigNat#
    b #) of
          (# Bool#
    1#, Bool#
    1# #) -> Word# -> BigNat#
    bigNatFromWord# (Word# -> Word# -> Word#
    gcdWord# (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    a Bool#
    0#)
                                                    (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    b Bool#
    0#))
          (# Bool#
    1#, Bool#
    _  #) -> Word# -> BigNat#
    bigNatFromWord# (BigNat# -> Word# -> Word#
    bigNatGcdWord# BigNat#
    b (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    a Bool#
    0#))
          (# Bool#
    _ , Bool#
    1# #) -> Word# -> BigNat#
    bigNatFromWord# (BigNat# -> Word# -> Word#
    bigNatGcdWord# BigNat#
    a (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    b Bool#
    0#))
          (# Bool#, Bool# #)
    _            ->
             let
                go :: BigNat# -> BigNat# -> BigNat#
    go BigNat#
    wx BigNat#
    wy = -- wx > wy
                   Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# (BigNat# -> Bool#
    wordArraySize# BigNat#
    wy) \MutableWordArray# RealWorld
    mwr State# RealWorld
    s ->
                      MutableWordArray# RealWorld
    -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
    bignat_gcd MutableWordArray# RealWorld
    mwr BigNat#
    wx BigNat#
    wy State# RealWorld
    s
             in case BigNat# -> BigNat# -> Ordering
    bigNatCompare BigNat#
    a BigNat#
    b of
                   Ordering
    EQ -> BigNat#
    a
                   Ordering
    LT -> BigNat# -> BigNat# -> BigNat#
    go BigNat#
    b BigNat#
    a
                   Ordering
    GT -> BigNat# -> BigNat# -> BigNat#
    go BigNat#
    a BigNat#
    b

    -- | Greatest common divisor
    bigNatGcdWord# :: BigNat# -> Word# -> Word#
    bigNatGcdWord# :: BigNat# -> Word# -> Word#
    bigNatGcdWord# BigNat#
    a Word#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = Word#
    0##
       | Word#
    0## <- Word#
    b       = Word#
    0##
       | BigNat# -> Bool
    bigNatIsOne BigNat#
    a  = Word#
    1##
       | Word#
    1## <- Word#
    b       = Word#
    1##
       | Bool
    True           = case BigNat# -> Word# -> Ordering
    bigNatCompareWord# BigNat#
    a Word#
    b of
          Ordering
    EQ -> Word#
    b
          Ordering
    _  -> BigNat# -> Word# -> Word#
    bignat_gcd_word BigNat#
    a Word#
    b

    -- | Least common multiple
    bigNatLcm :: BigNat# -> BigNat# -> BigNat#
    bigNatLcm :: BigNat# -> BigNat# -> BigNat#
    bigNatLcm BigNat#
    a BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = Void# -> BigNat#
    bigNatZero# Void#
    void#
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b = Void# -> BigNat#
    bigNatZero# Void#
    void#
       | BigNat# -> Bool
    bigNatIsOne  BigNat#
    a = BigNat#
    b
       | BigNat# -> Bool
    bigNatIsOne  BigNat#
    b = BigNat#
    a
       | Bool
    True
       = case (# BigNat# -> Bool#
    bigNatSize# BigNat#
    a, BigNat# -> Bool#
    bigNatSize# BigNat#
    b #) of
          (# Bool#
    1#, Bool#
    1# #) -> Word# -> Word# -> BigNat#
    bigNatLcmWordWord# (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    a Bool#
    0#) (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    b Bool#
    0#)
          (# Bool#
    1#, Bool#
    _  #) -> BigNat# -> Word# -> BigNat#
    bigNatLcmWord# BigNat#
    b (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    a Bool#
    0#)
          (# Bool#
    _ , Bool#
    1# #) -> BigNat# -> Word# -> BigNat#
    bigNatLcmWord# BigNat#
    a (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    b Bool#
    0#)
          (# Bool#, Bool# #)
    _            -> (BigNat#
    a BigNat# -> BigNat# -> BigNat#
    `bigNatQuot` (BigNat#
    a BigNat# -> BigNat# -> BigNat#
    `bigNatGcd` BigNat#
    b)) BigNat# -> BigNat# -> BigNat#
    `bigNatMul` BigNat#
    b
                           -- TODO: use extended GCD to get a's factor directly

    -- | Least common multiple with a Word#
    bigNatLcmWord# :: BigNat# -> Word# -> BigNat#
    bigNatLcmWord# :: BigNat# -> Word# -> BigNat#
    bigNatLcmWord# BigNat#
    a Word#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a      = Void# -> BigNat#
    bigNatZero# Void#
    void#
       | Word#
    0## <- Word#
    b            = Void# -> BigNat#
    bigNatZero# Void#
    void#
       | BigNat# -> Bool
    bigNatIsOne  BigNat#
    a      = Word# -> BigNat#
    bigNatFromWord# Word#
    b
       | Word#
    1## <- Word#
    b            = BigNat#
    a
       | Bool#
    1# <- BigNat# -> Bool#
    bigNatSize# BigNat#
    a = Word# -> Word# -> BigNat#
    bigNatLcmWordWord# (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    a Bool#
    0#) Word#
    b
       | Bool
    True
       = (BigNat#
    a BigNat# -> Word# -> BigNat#
    `bigNatQuotWord#` (BigNat#
    a BigNat# -> Word# -> Word#
    `bigNatGcdWord#` Word#
    b)) BigNat# -> Word# -> BigNat#
    `bigNatMulWord#` Word#
    b
          -- TODO: use extended GCD to get a's factor directly

    -- | Least common multiple between two Word#
    bigNatLcmWordWord# :: Word# -> Word# -> BigNat#
    bigNatLcmWordWord# :: Word# -> Word# -> BigNat#
    bigNatLcmWordWord# Word#
    a Word#
    b
       | Word#
    0## <- Word#
    a = Void# -> BigNat#
    bigNatZero# Void#
    void#
       | Word#
    0## <- Word#
    b = Void# -> BigNat#
    bigNatZero# Void#
    void#
       | Word#
    1## <- Word#
    a = Word# -> BigNat#
    bigNatFromWord# Word#
    b
       | Word#
    1## <- Word#
    b = Word# -> BigNat#
    bigNatFromWord# Word#
    a
       | Bool
    True     = case (Word#
    a Word# -> Word# -> Word#
    `quotWord#` (Word#
    a Word# -> Word# -> Word#
    `gcdWord#` Word#
    b)) Word# -> Word# -> (# Word#, Word# #)
    `timesWord2#` Word#
    b of
                         -- TODO: use extended GCD to get a's factor directly
          (# Word#
    h, Word#
    l #) -> Word# -> Word# -> BigNat#
    bigNatFromWord2# Word#
    h Word#
    l

    -------------------------------------------------
    -- Bitwise operations
    -------------------------------------------------

    -- | Bitwise OR
    bigNatOr :: BigNat# -> BigNat# -> BigNat#
    bigNatOr :: BigNat# -> BigNat# -> BigNat#
    bigNatOr BigNat#
    a BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b = BigNat#
    a
       | Bool
    True           = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArray# Bool#
    sz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                            (MutableWordArray# RealWorld
     -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
    bignat_or MutableWordArray# RealWorld
    mwa BigNat#
    a BigNat#
    b State# RealWorld
    s
       where
          !szA :: Bool#
    szA = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          !szB :: Bool#
    szB = BigNat# -> Bool#
    wordArraySize# BigNat#
    b
          !sz :: Bool#
    sz  = Bool# -> Bool# -> Bool#
    maxI# Bool#
    szA Bool#
    szB

    -- | Bitwise OR with Word#
    bigNatOrWord# :: BigNat# -> Word# -> BigNat#
    bigNatOrWord# :: BigNat# -> Word# -> BigNat#
    bigNatOrWord# BigNat#
    a Word#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = Word# -> BigNat#
    bigNatFromWord# Word#
    b
       | Word#
    0## <- Word#
    b       = BigNat#
    a
       | Bool
    True           =
          let sz :: Bool#
    sz = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          in Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArray# Bool#
    sz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                case MutableWordArray# RealWorld
    -> Bool#
    -> BigNat#
    -> Bool#
    -> Bool#
    -> State# RealWorld
    -> State# RealWorld
    forall s.
    MutableByteArray# s
    -> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
    mwaArrayCopy# MutableWordArray# RealWorld
    mwa Bool#
    1# BigNat#
    a Bool#
    1# (Bool#
    sz Bool# -> Bool# -> Bool#
    -# Bool#
    1#) State# RealWorld
    s of
                   State# RealWorld
    s' -> MutableWordArray# RealWorld
    -> Bool# -> Word# -> State# RealWorld -> State# RealWorld
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# RealWorld
    mwa Bool#
    0# (BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a Bool#
    0# Word# -> Word# -> Word#
    `or#` Word#
    b) State# RealWorld
    s'

    -- | Bitwise AND
    bigNatAnd :: BigNat# -> BigNat# -> BigNat#
    bigNatAnd :: BigNat# -> BigNat# -> BigNat#
    bigNatAnd BigNat#
    a BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = BigNat#
    a
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b = BigNat#
    b
       | Bool
    True           = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# Bool#
    sz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                            (MutableWordArray# RealWorld
     -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
    bignat_and MutableWordArray# RealWorld
    mwa BigNat#
    a BigNat#
    b State# RealWorld
    s
       where
          !szA :: Bool#
    szA = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          !szB :: Bool#
    szB = BigNat# -> Bool#
    wordArraySize# BigNat#
    b
          !sz :: Bool#
    sz  = Bool# -> Bool# -> Bool#
    minI# Bool#
    szA Bool#
    szB

    -- | Bitwise ANDNOT
    bigNatAndNot :: BigNat# -> BigNat# -> BigNat#
    bigNatAndNot :: BigNat# -> BigNat# -> BigNat#
    bigNatAndNot BigNat#
    a BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = BigNat#
    a
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b = BigNat#
    a
       | Bool
    True           = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# Bool#
    szA \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                            (MutableWordArray# RealWorld
     -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
    bignat_and_not MutableWordArray# RealWorld
    mwa BigNat#
    a BigNat#
    b State# RealWorld
    s
       where
          !szA :: Bool#
    szA = BigNat# -> Bool#
    wordArraySize# BigNat#
    a

    -- | Bitwise AND with Word#
    bigNatAndWord# :: BigNat# -> Word# -> BigNat#
    bigNatAndWord# :: BigNat# -> Word# -> BigNat#
    bigNatAndWord# BigNat#
    a Word#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = BigNat#
    a
       | Bool
    True           = Word# -> BigNat#
    bigNatFromWord# (BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a Bool#
    0# Word# -> Word# -> Word#
    `and#` Word#
    b)

    -- | Bitwise ANDNOT with Word#
    bigNatAndNotWord# :: BigNat# -> Word# -> BigNat#
    bigNatAndNotWord# :: BigNat# -> Word# -> BigNat#
    bigNatAndNotWord# BigNat#
    a Word#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a     = BigNat#
    a
       | Bool#
    szA <- BigNat# -> Bool#
    bigNatSize# BigNat#
    a
       = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArray# Bool#
    szA \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
          -- duplicate higher limbs
          case MutableWordArray# RealWorld
    -> Bool#
    -> BigNat#
    -> Bool#
    -> Bool#
    -> State# RealWorld
    -> State# RealWorld
    forall s.
    MutableByteArray# s
    -> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
    mwaArrayCopy# MutableWordArray# RealWorld
    mwa Bool#
    1# BigNat#
    a Bool#
    1# (Bool#
    szA Bool# -> Bool# -> Bool#
    -# Bool#
    1#) State# RealWorld
    s of
             State# RealWorld
    s' -> MutableWordArray# RealWorld
    -> Bool# -> Word# -> State# RealWorld -> State# RealWorld
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    writeWordArray# MutableWordArray# RealWorld
    mwa Bool#
    0#
                   (BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a Bool#
    0# Word# -> Word# -> Word#
    `and#` Word# -> Word#
    not# Word#
    b) State# RealWorld
    s'

    -- | Bitwise AND with Int#
    bigNatAndInt# :: BigNat# -> Int# -> BigNat#
    bigNatAndInt# :: BigNat# -> Bool# -> BigNat#
    bigNatAndInt# BigNat#
    a Bool#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a     = BigNat#
    a
       | Bool# -> Bool
    isTrue# (Bool#
    b Bool# -> Bool# -> Bool#
    >=# Bool#
    0#) = BigNat# -> Word# -> BigNat#
    bigNatAndWord# BigNat#
    a (Bool# -> Word#
    int2Word# Bool#
    b)
       | Bool#
    szA <- BigNat# -> Bool#
    bigNatSize# BigNat#
    a
       = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArray# Bool#
    szA \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
          -- duplicate higher limbs (because of sign-extension of b)
          case MutableWordArray# RealWorld
    -> Bool#
    -> BigNat#
    -> Bool#
    -> Bool#
    -> State# RealWorld
    -> State# RealWorld
    forall s.
    MutableByteArray# s
    -> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
    mwaArrayCopy# MutableWordArray# RealWorld
    mwa Bool#
    1# BigNat#
    a Bool#
    1# (Bool#
    szA Bool# -> Bool# -> Bool#
    -# Bool#
    1#) State# RealWorld
    s of
             State# RealWorld
    s' -> MutableWordArray# RealWorld
    -> Bool# -> Word# -> State# RealWorld -> State# RealWorld
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    writeWordArray# MutableWordArray# RealWorld
    mwa Bool#
    0#
                   (BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a Bool#
    0# Word# -> Word# -> Word#
    `and#` Bool# -> Word#
    int2Word# Bool#
    b) State# RealWorld
    s'

    -- | Bitwise XOR
    bigNatXor :: BigNat# -> BigNat# -> BigNat#
    bigNatXor :: BigNat# -> BigNat# -> BigNat#
    bigNatXor BigNat#
    a BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = BigNat#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b = BigNat#
    a
       | Bool
    True           = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# Bool#
    sz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                            (MutableWordArray# RealWorld
     -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
    bignat_xor MutableWordArray# RealWorld
    mwa BigNat#
    a BigNat#
    b State# RealWorld
    s
       where
          !szA :: Bool#
    szA = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          !szB :: Bool#
    szB = BigNat# -> Bool#
    wordArraySize# BigNat#
    b
          !sz :: Bool#
    sz  = Bool# -> Bool# -> Bool#
    maxI# Bool#
    szA Bool#
    szB

    -- | Bitwise XOR with Word#
    bigNatXorWord# :: BigNat# -> Word# -> BigNat#
    bigNatXorWord# :: BigNat# -> Word# -> BigNat#
    bigNatXorWord# BigNat#
    a Word#
    b
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = Word# -> BigNat#
    bigNatFromWord# Word#
    b
       | Word#
    0## <- Word#
    b       = BigNat#
    a
       | Bool
    True           =
          let
             sz :: Bool#
    sz = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          in Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArray# Bool#
    sz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                case MutableWordArray# RealWorld
    -> Bool#
    -> BigNat#
    -> Bool#
    -> Bool#
    -> State# RealWorld
    -> State# RealWorld
    forall s.
    MutableByteArray# s
    -> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
    mwaArrayCopy# MutableWordArray# RealWorld
    mwa Bool#
    1# BigNat#
    a Bool#
    1# (Bool#
    sz Bool# -> Bool# -> Bool#
    -# Bool#
    1#) State# RealWorld
    s of
                   State# RealWorld
    s' -> MutableWordArray# RealWorld
    -> Bool# -> Word# -> State# RealWorld -> State# RealWorld
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# RealWorld
    mwa Bool#
    0# (BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a Bool#
    0# Word# -> Word# -> Word#
    `xor#` Word#
    b) State# RealWorld
    s'

    -- | PopCount for BigNat
    bigNatPopCount :: BigNat# -> Word
    bigNatPopCount :: BigNat# -> Word
    bigNatPopCount BigNat#
    a = Word# -> Word
    W# (BigNat# -> Word#
    bigNatPopCount# BigNat#
    a)

    -- | PopCount for BigNat
    bigNatPopCount# :: BigNat# -> Word#
    bigNatPopCount# :: BigNat# -> Word#
    bigNatPopCount# BigNat#
    a
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = Word#
    0##
       | Bool
    True           = (BigNat# -> Word#) -> BigNat# -> Word#
    forall a. a -> a
    inline BigNat# -> Word#
    bignat_popcount BigNat#
    a

    -- | Bit shift right
    bigNatShiftR# :: BigNat# -> Word# -> BigNat#
    bigNatShiftR# :: BigNat# -> Word# -> BigNat#
    bigNatShiftR# BigNat#
    a Word#
    n
       | Word#
    0## <- Word#
    n
       = BigNat#
    a

       | Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    wordArraySize# BigNat#
    a Bool# -> Bool# -> Bool#
    ==# Bool#
    0#)
       = BigNat#
    a

       | Bool#
    nw <- Word# -> Bool#
    word2Int# (Word#
    n Word# -> Bool# -> Word#
    `uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
       , Bool# -> Bool
    isTrue# (Bool#
    nw Bool# -> Bool# -> Bool#
    >=# BigNat# -> Bool#
    wordArraySize# BigNat#
    a)
       = Void# -> BigNat#
    bigNatZero# Void#
    void#

       | Bool
    True
       = let
          !szA :: Bool#
    szA = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          !nw :: Bool#
    nw  = Word# -> Bool#
    word2Int# (Word#
    n Word# -> Bool# -> Word#
    `uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
          !sz :: Bool#
    sz  = Bool#
    szA Bool# -> Bool# -> Bool#
    -# Bool#
    nw
         in Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# Bool#
    sz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
             (MutableWordArray# RealWorld
     -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> Word#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld
    bignat_shiftr MutableWordArray# RealWorld
    mwa BigNat#
    a Word#
    n State# RealWorld
    s

    -- | Bit shift right (two's complement)
    bigNatShiftRNeg# :: BigNat# -> Word# -> BigNat#
    bigNatShiftRNeg# :: BigNat# -> Word# -> BigNat#
    bigNatShiftRNeg# BigNat#
    a Word#
    n
       | Word#
    0## <- Word#
    n
       = BigNat#
    a

       | Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    wordArraySize# BigNat#
    a Bool# -> Bool# -> Bool#
    ==# Bool#
    0#)
       = BigNat#
    a

       | Bool#
    nw <- Word# -> Bool#
    word2Int# (Word#
    n Word# -> Bool# -> Word#
    `uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
       , Bool# -> Bool
    isTrue# (Bool#
    nw Bool# -> Bool# -> Bool#
    >=# BigNat# -> Bool#
    wordArraySize# BigNat#
    a)
       = Void# -> BigNat#
    bigNatZero# Void#
    void#

       | Bool
    True
       = let
          !szA :: Bool#
    szA = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          !nw :: Bool#
    nw  = (Word# -> Bool#
    word2Int# Word#
    n Bool# -> Bool# -> Bool#
    -# Bool#
    1#) Bool# -> Bool# -> Bool#
    `uncheckedIShiftRL#` WORD_SIZE_BITS_SHIFT#
          !sz :: Bool#
    sz  = Bool#
    szA Bool# -> Bool# -> Bool#
    -# Bool#
    nw
         in Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# Bool#
    sz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
             (MutableWordArray# RealWorld
     -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> Word#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld
    bignat_shiftr_neg MutableWordArray# RealWorld
    mwa BigNat#
    a Word#
    n State# RealWorld
    s

    -- | Bit shift right
    bigNatShiftR :: BigNat# -> Word -> BigNat#
    bigNatShiftR :: BigNat# -> Word -> BigNat#
    bigNatShiftR BigNat#
    a (W# Word#
    n) = BigNat# -> Word# -> BigNat#
    bigNatShiftR# BigNat#
    a Word#
    n

    -- | Bit shift left
    bigNatShiftL :: BigNat# -> Word -> BigNat#
    bigNatShiftL :: BigNat# -> Word -> BigNat#
    bigNatShiftL BigNat#
    a (W# Word#
    n) = BigNat# -> Word# -> BigNat#
    bigNatShiftL# BigNat#
    a Word#
    n

    -- | Bit shift left
    bigNatShiftL# :: BigNat# -> Word# -> BigNat#
    bigNatShiftL# :: BigNat# -> Word# -> BigNat#
    bigNatShiftL# BigNat#
    a Word#
    n
       | Word#
    0## <- Word#
    n
       = BigNat#
    a

       | Bool# -> Bool
    isTrue# (BigNat# -> Bool#
    wordArraySize# BigNat#
    a Bool# -> Bool# -> Bool#
    ==# Bool#
    0#)
       = BigNat#
    a

       | Bool
    True
       = let
          !szA :: Bool#
    szA = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          !nw :: Bool#
    nw  = Word# -> Bool#
    word2Int# (Word#
    n Word# -> Bool# -> Word#
    `uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
          !nb :: Bool#
    nb  = Word# -> Bool#
    word2Int# (Word#
    n Word# -> Word# -> Word#
    `and#` WORD_SIZE_BITS_MASK##)
          !sz :: Bool#
    sz   = Bool#
    szA Bool# -> Bool# -> Bool#
    +# Bool#
    nw Bool# -> Bool# -> Bool#
    +# (Bool#
    nb Bool# -> Bool# -> Bool#
    /=# Bool#
    0#)

         in Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# Bool#
    sz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
             (MutableWordArray# RealWorld
     -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> Word#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld
    bignat_shiftl MutableWordArray# RealWorld
    mwa BigNat#
    a Word#
    n State# RealWorld
    s

    -- | BigNat bit test
    bigNatTestBit# :: BigNat# -> Word# -> Bool#
    bigNatTestBit# :: BigNat# -> Word# -> Bool#
    bigNatTestBit# BigNat#
    a Word#
    n =
       let
          !sz :: Bool#
    sz = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          !nw :: Bool#
    nw = Word# -> Bool#
    word2Int# (Word#
    n Word# -> Bool# -> Word#
    `uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
          !nb :: Word#
    nb = Word#
    n Word# -> Word# -> Word#
    `and#` WORD_SIZE_BITS_MASK##
       in if
          | Bool# -> Bool
    isTrue# (Bool#
    nw Bool# -> Bool# -> Bool#
    >=# Bool#
    sz) -> Bool#
    0#
          | Bool
    True                -> Word# -> Word# -> Bool#
    testBitW# (BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a Bool#
    nw) Word#
    nb

    -- | BigNat bit test
    bigNatTestBit :: BigNat# -> Word -> Bool
    bigNatTestBit :: BigNat# -> Word -> Bool
    bigNatTestBit BigNat#
    a (W# Word#
    n) = Bool# -> Bool
    isTrue# (BigNat# -> Word# -> Bool#
    bigNatTestBit# BigNat#
    a Word#
    n)

    -- | Return a BigNat whose bit `i` is the only one set.
    --
    -- Specialized version of `bigNatShiftL (bigNatFromWord# 1##)`
    --
    bigNatBit# :: Word# -> BigNat#
    bigNatBit# :: Word# -> BigNat#
    bigNatBit# Word#
    i
       | Word#
    0## <- Word#
    i = Void# -> BigNat#
    bigNatOne# Void#
    void#
       | Bool
    True =
       let
          !nw :: Bool#
    nw = Word# -> Bool#
    word2Int# (Word#
    i Word# -> Bool# -> Word#
    `uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
          !nb :: Bool#
    nb = Word# -> Bool#
    word2Int# (Word#
    i Word# -> Word# -> Word#
    `and#` WORD_SIZE_BITS_MASK##)
          !sz :: Bool#
    sz = Bool#
    nw Bool# -> Bool# -> Bool#
    +# Bool#
    1#
          !v :: Word#
    v  = Word#
    1## Word# -> Bool# -> Word#
    `uncheckedShiftL#` Bool#
    nb
       in Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArray# Bool#
    sz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
             -- clear the array
             case MutableWordArray# RealWorld
    -> Word# -> Word# -> Word# -> State# RealWorld -> State# RealWorld
    forall s.
    MutableWordArray# s
    -> Word# -> Word# -> Word# -> State# s -> State# s
    mwaFill# MutableWordArray# RealWorld
    mwa Word#
    0## Word#
    0## (Bool# -> Word#
    int2Word# Bool#
    sz) State# RealWorld
    s of
                -- set the bit in the most-significant word
                State# RealWorld
    s2 -> MutableWordArray# RealWorld
    -> Bool# -> Word# -> State# RealWorld -> State# RealWorld
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# RealWorld
    mwa (Bool#
    sz Bool# -> Bool# -> Bool#
    -# Bool#
    1#) Word#
    v State# RealWorld
    s2

    -- | Return a BigNat whose bit `i` is the only one set.
    --
    -- Specialized version of `bigNatShiftL (bigNatFromWord# 1##)`
    --
    bigNatBit :: Word -> BigNat#
    bigNatBit :: Word -> BigNat#
    bigNatBit (W# Word#
    i) = Word# -> BigNat#
    bigNatBit# Word#
    i

    -- | BigNat clear bit
    bigNatClearBit# :: BigNat# -> Word# -> BigNat#
    bigNatClearBit# :: BigNat# -> Word# -> BigNat#
    bigNatClearBit# BigNat#
    a Word#
    n
       -- check the range validity and the current bit value
       | Bool# -> Bool
    isTrue# (BigNat# -> Word# -> Bool#
    bigNatTestBit# BigNat#
    a Word#
    n Bool# -> Bool# -> Bool#
    ==# Bool#
    0#) = BigNat#
    a
       | Bool
    True
       = let
          !sz :: Bool#
    sz = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          !nw :: Bool#
    nw = Word# -> Bool#
    word2Int# (Word#
    n Word# -> Bool# -> Word#
    `uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
          !nb :: Bool#
    nb = Word# -> Bool#
    word2Int# (Word#
    n Word# -> Word# -> Word#
    `and#` WORD_SIZE_BITS_MASK##)
          !nv :: Word#
    nv = BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    a Bool#
    nw Word# -> Word# -> Word#
    `xor#` Bool# -> Word#
    bitW# Bool#
    nb
       in if
          | Bool# -> Bool
    isTrue# (Bool#
    sz Bool# -> Bool# -> Bool#
    ==# Bool#
    1#)
          -> Word# -> BigNat#
    bigNatFromWord# Word#
    nv

          -- special case, operating on most-significant Word
          | Word#
    0## <- Word#
    nv
          , Bool# -> Bool
    isTrue# (Bool#
    nw Bool# -> Bool# -> Bool#
    +# Bool#
    1# Bool# -> Bool# -> Bool#
    ==# Bool#
    sz)
          -> case Bool#
    sz Bool# -> Bool# -> Bool#
    -# (BigNat# -> Bool# -> Bool#
    waClzAt BigNat#
    a (Bool#
    sz Bool# -> Bool# -> Bool#
    -# Bool#
    2#) Bool# -> Bool# -> Bool#
    +# Bool#
    1#) of
                Bool#
    0#  -> Void# -> BigNat#
    bigNatZero# Void#
    void#
                Bool#
    nsz -> Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArray# Bool#
    nsz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                         MutableWordArray# RealWorld
    -> Bool#
    -> BigNat#
    -> Bool#
    -> Bool#
    -> State# RealWorld
    -> State# RealWorld
    forall s.
    MutableByteArray# s
    -> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
    mwaArrayCopy# MutableWordArray# RealWorld
    mwa Bool#
    0# BigNat#
    a Bool#
    0# Bool#
    nsz State# RealWorld
    s

          | Bool
    True ->
             Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArray# Bool#
    sz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                case MutableWordArray# RealWorld
    -> Bool#
    -> BigNat#
    -> Bool#
    -> Bool#
    -> State# RealWorld
    -> State# RealWorld
    forall s.
    MutableByteArray# s
    -> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
    mwaArrayCopy# MutableWordArray# RealWorld
    mwa Bool#
    0# BigNat#
    a Bool#
    0# Bool#
    sz State# RealWorld
    s of
                   State# RealWorld
    s' -> MutableWordArray# RealWorld
    -> Bool# -> Word# -> State# RealWorld -> State# RealWorld
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    writeWordArray# MutableWordArray# RealWorld
    mwa Bool#
    nw Word#
    nv State# RealWorld
    s'

    -- | BigNat set bit
    bigNatSetBit# :: BigNat# -> Word# -> BigNat#
    bigNatSetBit# :: BigNat# -> Word# -> BigNat#
    bigNatSetBit# BigNat#
    a Word#
    n
       -- check the current bit value
       | Bool# -> Bool
    isTrue# (BigNat# -> Word# -> Bool#
    bigNatTestBit# BigNat#
    a Word#
    n) = BigNat#
    a
       | Bool
    True
       = let
          !sz :: Bool#
    sz = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
          !nw :: Bool#
    nw = Word# -> Bool#
    word2Int# (Word#
    n Word# -> Bool# -> Word#
    `uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
          !nb :: Bool#
    nb = Word# -> Bool#
    word2Int# (Word#
    n Word# -> Word# -> Word#
    `and#` WORD_SIZE_BITS_MASK##)
          d :: Bool#
    d   = Bool#
    nw Bool# -> Bool# -> Bool#
    +# Bool#
    1# Bool# -> Bool# -> Bool#
    -# Bool#
    sz
       in if
          -- result BigNat will have more limbs
          | Bool# -> Bool
    isTrue# (Bool#
    d Bool# -> Bool# -> Bool#
    ># Bool#
    0#)
          -> Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArray# (Bool#
    nw Bool# -> Bool# -> Bool#
    +# Bool#
    1#) \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                case MutableWordArray# RealWorld
    -> Bool#
    -> BigNat#
    -> Bool#
    -> Bool#
    -> State# RealWorld
    -> State# RealWorld
    forall s.
    MutableByteArray# s
    -> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
    mwaArrayCopy# MutableWordArray# RealWorld
    mwa Bool#
    0# BigNat#
    a Bool#
    0# Bool#
    sz State# RealWorld
    s of
                   State# RealWorld
    s' -> case MutableWordArray# RealWorld
    -> Word# -> Word# -> Word# -> State# RealWorld -> State# RealWorld
    forall s.
    MutableWordArray# s
    -> Word# -> Word# -> Word# -> State# s -> State# s
    mwaFill# MutableWordArray# RealWorld
    mwa Word#
    0## (Bool# -> Word#
    int2Word# Bool#
    sz) (Bool# -> Word#
    int2Word# (Bool#
    d Bool# -> Bool# -> Bool#
    -# Bool#
    1#)) State# RealWorld
    s' of
                      State# RealWorld
    s'' -> MutableWordArray# RealWorld
    -> Bool# -> Word# -> State# RealWorld -> State# RealWorld
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    writeWordArray# MutableWordArray# RealWorld
    mwa Bool#
    nw (Bool# -> Word#
    bitW# Bool#
    nb) State# RealWorld
    s''

          | Word#
    nv <- BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    a Bool#
    nw Word# -> Word# -> Word#
    `or#` Bool# -> Word#
    bitW# Bool#
    nb
          -> Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArray# Bool#
    sz \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                case MutableWordArray# RealWorld
    -> Bool#
    -> BigNat#
    -> Bool#
    -> Bool#
    -> State# RealWorld
    -> State# RealWorld
    forall s.
    MutableByteArray# s
    -> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
    mwaArrayCopy# MutableWordArray# RealWorld
    mwa Bool#
    0# BigNat#
    a Bool#
    0# Bool#
    sz State# RealWorld
    s of
                   State# RealWorld
    s' -> MutableWordArray# RealWorld
    -> Bool# -> Word# -> State# RealWorld -> State# RealWorld
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    writeWordArray# MutableWordArray# RealWorld
    mwa Bool#
    nw Word#
    nv State# RealWorld
    s'

    -- | Reverse the given bit
    bigNatComplementBit# :: BigNat# -> Word# -> BigNat#
    bigNatComplementBit# :: BigNat# -> Word# -> BigNat#
    bigNatComplementBit# BigNat#
    bn Word#
    i
      | Bool# -> Bool
    isTrue# (BigNat# -> Word# -> Bool#
    bigNatTestBit# BigNat#
    bn Word#
    i) = BigNat# -> Word# -> BigNat#
    bigNatClearBit# BigNat#
    bn Word#
    i
      | Bool
    True                          = BigNat# -> Word# -> BigNat#
    bigNatSetBit#   BigNat#
    bn Word#
    i

    -------------------------------------------------
    -- Log operations
    -------------------------------------------------

    -- | Base 2 logarithm
    bigNatLog2# :: BigNat# -> Word#
    bigNatLog2# :: BigNat# -> Word#
    bigNatLog2# BigNat#
    a
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = Word#
    0##
       | Bool
    True           =
          let i :: Word#
    i = Bool# -> Word#
    int2Word# (BigNat# -> Bool#
    bigNatSize# BigNat#
    a) Word# -> Word# -> Word#
    `minusWord#` Word#
    1##
          in Word# -> Word#
    wordLog2# (BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    a (Word# -> Bool#
    word2Int# Word#
    i))
             Word# -> Word# -> Word#
    `plusWord#` (Word#
    i Word# -> Bool# -> Word#
    `uncheckedShiftL#` WORD_SIZE_BITS_SHIFT#)

    -- | Base 2 logarithm
    bigNatLog2 :: BigNat# -> Word
    bigNatLog2 :: BigNat# -> Word
    bigNatLog2 BigNat#
    a = Word# -> Word
    W# (BigNat# -> Word#
    bigNatLog2# BigNat#
    a)

    -- | Logarithm for an arbitrary base
    bigNatLogBase# :: BigNat# -> BigNat# -> Word#
    bigNatLogBase# :: BigNat# -> BigNat# -> Word#
    bigNatLogBase# BigNat#
    base BigNat#
    a
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    base Bool -> Bool -> Bool
    || BigNat# -> Bool
    bigNatIsOne BigNat#
    base
       = Void# -> Word#
    unexpectedValue_Word# Void#
    void#

       | Bool#
    1# <- BigNat# -> Bool#
    bigNatSize# BigNat#
    base
       , Word#
    2## <- BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    base Bool#
    0#
       = BigNat# -> Word#
    bigNatLog2# BigNat#
    a

       -- TODO: optimize log base power of 2 (256, etc.)

       | Bool
    True
       = case BigNat# -> (# BigNat#, Word# #)
    go BigNat#
    base of (# BigNat#
    _, Word#
    e' #) -> Word#
    e'
       where
          go :: BigNat# -> (# BigNat#, Word# #)
    go BigNat#
    pw = if BigNat#
    a BigNat# -> BigNat# -> Bool
    `bigNatLt` BigNat#
    pw
             then (# BigNat#
    a, Word#
    0## #)
             else case BigNat# -> (# BigNat#, Word# #)
    go (BigNat# -> BigNat#
    bigNatSqr BigNat#
    pw) of
              (# BigNat#
    q, Word#
    e #) -> if BigNat#
    q BigNat# -> BigNat# -> Bool
    `bigNatLt` BigNat#
    pw
                then (# BigNat#
    q, Word#
    2## Word# -> Word# -> Word#
    `timesWord#` Word#
    e #)
                else (# BigNat#
    q BigNat# -> BigNat# -> BigNat#
    `bigNatQuot` BigNat#
    pw
                     , (Word#
    2## Word# -> Word# -> Word#
    `timesWord#` Word#
    e) Word# -> Word# -> Word#
    `plusWord#` Word#
    1## #)

    -- | Logarithm for an arbitrary base
    bigNatLogBase :: BigNat# -> BigNat# -> Word
    bigNatLogBase :: BigNat# -> BigNat# -> Word
    bigNatLogBase BigNat#
    base BigNat#
    a = Word# -> Word
    W# (BigNat# -> BigNat# -> Word#
    bigNatLogBase# BigNat#
    base BigNat#
    a)

    -- | Logarithm for an arbitrary base
    bigNatLogBaseWord# :: Word# -> BigNat# -> Word#
    bigNatLogBaseWord# :: Word# -> BigNat# -> Word#
    bigNatLogBaseWord# Word#
    base BigNat#
    a
       | Word#
    0## <- Word#
    base = Void# -> Word#
    unexpectedValue_Word# Void#
    void#
       | Word#
    1## <- Word#
    base = Void# -> Word#
    unexpectedValue_Word# Void#
    void#
       | Word#
    2## <- Word#
    base = BigNat# -> Word#
    bigNatLog2# BigNat#
    a
       -- TODO: optimize log base power of 2 (256, etc.)
       | Bool
    True = BigNat# -> BigNat# -> Word#
    bigNatLogBase# (Word# -> BigNat#
    bigNatFromWord# Word#
    base) BigNat#
    a

    -- | Logarithm for an arbitrary base
    bigNatLogBaseWord :: Word -> BigNat# -> Word
    bigNatLogBaseWord :: Word -> BigNat# -> Word
    bigNatLogBaseWord (W# Word#
    base) BigNat#
    a = Word# -> Word
    W# (Word# -> BigNat# -> Word#
    bigNatLogBaseWord# Word#
    base BigNat#
    a)

    -------------------------------------------------
    -- Various
    -------------------------------------------------

    -- | Compute the number of digits of the BigNat in the given base.
    --
    -- `base` must be > 1
    bigNatSizeInBase# :: Word# -> BigNat# -> Word#
    bigNatSizeInBase# :: Word# -> BigNat# -> Word#
    bigNatSizeInBase# Word#
    base BigNat#
    a
       | Bool# -> Bool
    isTrue# (Word#
    base Word# -> Word# -> Bool#
    `leWord#` Word#
    1##)
       = Void# -> Word#
    unexpectedValue_Word# Void#
    void#

       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a
       = Word#
    0##

       | Bool
    True
       = Word# -> BigNat# -> Word#
    bigNatLogBaseWord# Word#
    base BigNat#
    a Word# -> Word# -> Word#
    `plusWord#` Word#
    1##

    -- | Compute the number of digits of the BigNat in the given base.
    --
    -- `base` must be > 1
    bigNatSizeInBase :: Word -> BigNat# -> Word
    bigNatSizeInBase :: Word -> BigNat# -> Word
    bigNatSizeInBase (W# Word#
    w) BigNat#
    a = Word# -> Word
    W# (Word# -> BigNat# -> Word#
    bigNatSizeInBase# Word#
    w BigNat#
    a)

    -------------------------------------------------
    -- PowMod
    -------------------------------------------------

    -- Word# powMod shouldn't be here in BigNat. However GMP provides a very fast
    -- implementation so we keep this here at least until we get a native Haskell
    -- implementation as fast as GMP's one.

    powModWord# :: Word# -> Word# -> Word# -> Word#
    powModWord# :: Word# -> Word# -> Word# -> Word#
    powModWord# = Word# -> Word# -> Word# -> Word#
    bignat_powmod_words

    -- | \"@'bigNatPowModWord#' /b/ /e/ /m/@\" computes base @/b/@ raised to
    -- exponent @/e/@ modulo @/m/@.
    bigNatPowModWord# :: BigNat# -> BigNat# -> Word# -> Word#
    bigNatPowModWord# :: BigNat# -> BigNat# -> Word# -> Word#
    bigNatPowModWord# !BigNat#
    _ !BigNat#
    _ Word#
    0## = Void# -> Word#
    raiseDivZero_Word# Void#
    void#
    bigNatPowModWord# BigNat#
    _  BigNat#
    _  Word#
    1## = Word#
    0##
    bigNatPowModWord# BigNat#
    b  BigNat#
    e  Word#
    m
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    e         = Word#
    1##
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b         = Word#
    0##
       | BigNat# -> Bool
    bigNatIsOne  BigNat#
    b         = Word#
    1##
       | Bool
    True                   = BigNat# -> BigNat# -> Word# -> Word#
    bignat_powmod_word BigNat#
    b BigNat#
    e Word#
    m

    -- | \"@'bigNatPowMod' /b/ /e/ /m/@\" computes base @/b/@ raised to
    -- exponent @/e/@ modulo @/m/@.
    bigNatPowMod :: BigNat# -> BigNat# -> BigNat# -> BigNat#
    bigNatPowMod :: BigNat# -> BigNat# -> BigNat# -> BigNat#
    bigNatPowMod !BigNat#
    b !BigNat#
    e !BigNat#
    m
       | (# | Word#
    m' #) <- BigNat# -> (# (# #) | Word# #)
    bigNatToWordMaybe# BigNat#
    m
       = Word# -> BigNat#
    bigNatFromWord# (BigNat# -> BigNat# -> Word# -> Word#
    bigNatPowModWord# BigNat#
    b BigNat#
    e Word#
    m')
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    m = Void# -> BigNat#
    raiseDivZero_BigNat Void#
    void#
       | BigNat# -> Bool
    bigNatIsOne  BigNat#
    m = Word# -> BigNat#
    bigNatFromWord# Word#
    0##
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    e = Word# -> BigNat#
    bigNatFromWord# Word#
    1##
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    b = Word# -> BigNat#
    bigNatFromWord# Word#
    0##
       | BigNat# -> Bool
    bigNatIsOne  BigNat#
    b = Word# -> BigNat#
    bigNatFromWord# Word#
    1##
       | Bool
    True           = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArrayTrimed# (BigNat# -> Bool#
    bigNatSize# BigNat#
    m) \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                             (MutableWordArray# RealWorld
     -> BigNat#
     -> BigNat#
     -> BigNat#
     -> State# RealWorld
     -> State# RealWorld)
    -> MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> State# RealWorld
    forall a. a -> a
    inline MutableWordArray# RealWorld
    -> BigNat#
    -> BigNat#
    -> BigNat#
    -> State# RealWorld
    -> State# RealWorld
    bignat_powmod MutableWordArray# RealWorld
    mwa BigNat#
    b BigNat#
    e BigNat#
    m State# RealWorld
    s

    -- | Return count of trailing zero bits
    --
    -- Return 0 for zero BigNat
    bigNatCtz# :: BigNat# -> Word#
    bigNatCtz# :: BigNat# -> Word#
    bigNatCtz# BigNat#
    a
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = Word#
    0##
       | Bool
    True           = Bool# -> Word# -> Word#
    go Bool#
    0# Word#
    0##
          where
             go :: Bool# -> Word# -> Word#
    go Bool#
    i Word#
    c = case BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a Bool#
    i of
                Word#
    0## -> Bool# -> Word# -> Word#
    go (Bool#
    i Bool# -> Bool# -> Bool#
    +# Bool#
    1#) (Word#
    c Word# -> Word# -> Word#
    `plusWord#` WORD_SIZE_IN_BITS##)
                Word#
    w   -> Word# -> Word#
    ctz# Word#
    w Word# -> Word# -> Word#
    `plusWord#` Word#
    c

    -- | Return count of trailing zero bits
    --
    -- Return 0 for zero BigNat
    bigNatCtz :: BigNat# -> Word
    bigNatCtz :: BigNat# -> Word
    bigNatCtz BigNat#
    a = Word# -> Word
    W# (BigNat# -> Word#
    bigNatCtz# BigNat#
    a)

    -- | Return count of trailing zero words
    --
    -- Return 0 for zero BigNat
    bigNatCtzWord# :: BigNat# -> Word#
    bigNatCtzWord# :: BigNat# -> Word#
    bigNatCtzWord# BigNat#
    a
       | BigNat# -> Bool
    bigNatIsZero BigNat#
    a = Word#
    0##
       | Bool
    True           = Bool# -> Word# -> Word#
    go Bool#
    0# Word#
    0##
          where
             go :: Bool# -> Word# -> Word#
    go Bool#
    i Word#
    c = case BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a Bool#
    i of
                Word#
    0## -> Bool# -> Word# -> Word#
    go (Bool#
    i Bool# -> Bool# -> Bool#
    +# Bool#
    1#) (Word#
    c Word# -> Word# -> Word#
    `plusWord#` Word#
    1##)
                Word#
    _   -> Word#
    c

    -- | Return count of trailing zero words
    --
    -- Return 0 for zero BigNat
    bigNatCtzWord :: BigNat# -> Word
    bigNatCtzWord :: BigNat# -> Word
    bigNatCtzWord BigNat#
    a = Word# -> Word
    W# (BigNat# -> Word#
    bigNatCtzWord# BigNat#
    a)

    -------------------------------------------------
    -- Export to memory
    -------------------------------------------------

    -- | Write a BigNat in base-256 little-endian representation and return the
    -- number of bytes written.
    --
    -- Use \"@'bigNatSizeInBase' 256# /i/@\" to compute the exact number of bytes
    -- written in advance. In case of @/i/ == 0@, the function will write and report
    -- zero bytes written.
    bigNatToAddrLE# :: BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
    bigNatToAddrLE# :: forall s. BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
    bigNatToAddrLE# BigNat#
    a Addr#
    addr State# s
    s0
       | Bool# -> Bool
    isTrue# (Bool#
    sz Bool# -> Bool# -> Bool#
    ==# Bool#
    0#) = (# State# s
    s0, Word#
    0## #)
       | Bool
    True = case State# s -> (# State# s, Word# #)
    forall {s}. State# s -> (# State# s, Word# #)
    writeMSB State# s
    s0 of
          (# State# s
    s1, Word#
    k #) -> case Bool# -> State# s -> State# s
    forall {s}. Bool# -> State# s -> State# s
    go Bool#
    0# State# s
    s1 of
             State# s
    s2 -> (# State# s
    s2, Word#
    k Word# -> Word# -> Word#
    `plusWord#` (Bool# -> Word#
    int2Word# Bool#
    li Word# -> Bool# -> Word#
    `uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#) #)
       where
         !sz :: Bool#
    sz = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
         !li :: Bool#
    li = Bool#
    sz Bool# -> Bool# -> Bool#
    -# Bool#
    1#

         writeMSB :: State# s -> (# State# s, Word# #)
    writeMSB = Word# -> Addr# -> State# s -> (# State# s, Word# #)
    forall s. Word# -> Addr# -> State# s -> (# State# s, Word# #)
    wordToAddrLE# (BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a Bool#
    li)
                      (Addr#
    addr Addr# -> Bool# -> Addr#
    `plusAddr#` (Bool#
    li Bool# -> Bool# -> Bool#
    `uncheckedIShiftL#` WORD_SIZE_BYTES_SHIFT#))

         go :: Bool# -> State# s -> State# s
    go Bool#
    i State# s
    s
          | Bool# -> Bool
    isTrue# (Bool#
    i Bool# -> Bool# -> Bool#
    <# Bool#
    li)
          , Bool#
    off <- Bool#
    i Bool# -> Bool# -> Bool#
    `uncheckedIShiftL#` WORD_SIZE_BYTES_SHIFT#
          , Word#
    w <- BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a Bool#
    i
          = case Word# -> Addr# -> State# s -> State# s
    forall s. Word# -> Addr# -> State# s -> State# s
    wordWriteAddrLE# Word#
    w (Addr#
    addr Addr# -> Bool# -> Addr#
    `plusAddr#` Bool#
    off) State# s
    s of
             State# s
    s -> Bool# -> State# s -> State# s
    go (Bool#
    i Bool# -> Bool# -> Bool#
    +# Bool#
    1#) State# s
    s

          | Bool
    True
          = State# s
    s

    -- | Write a BigNat in base-256 big-endian representation and return the
    -- number of bytes written.
    --
    -- Use \"@'bigNatSizeInBase' 256# /i/@\" to compute the exact number of bytes
    -- written in advance. In case of @/i/ == 0@, the function will write and report
    -- zero bytes written.
    bigNatToAddrBE# :: BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
    bigNatToAddrBE# :: forall s. BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
    bigNatToAddrBE# BigNat#
    a Addr#
    addr State# s
    s0
       | Bool# -> Bool
    isTrue# (Bool#
    sz Bool# -> Bool# -> Bool#
    ==# Bool#
    0#) = (# State# s
    s0, Word#
    0## #)
       | Word#
    msw <- BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a (Bool#
    sz Bool# -> Bool# -> Bool#
    -# Bool#
    1#)
       = case Word# -> Addr# -> State# s -> (# State# s, Word# #)
    forall s. Word# -> Addr# -> State# s -> (# State# s, Word# #)
    wordToAddrBE# Word#
    msw Addr#
    addr State# s
    s0 of
          (# State# s
    s1, Word#
    k #) -> case Bool# -> Addr# -> State# s -> State# s
    forall {s}. Bool# -> Addr# -> State# s -> State# s
    go (Bool#
    sz Bool# -> Bool# -> Bool#
    -# Bool#
    1#) (Addr#
    addr Addr# -> Bool# -> Addr#
    `plusAddr#` Word# -> Bool#
    word2Int# Word#
    k) State# s
    s1 of
             State# s
    s2 -> (# State# s
    s2, Word#
    k Word# -> Word# -> Word#
    `plusWord#` (Bool# -> Word#
    int2Word# (Bool#
    sz Bool# -> Bool# -> Bool#
    -# Bool#
    1#) Word# -> Bool# -> Word#
    `uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#) #)
       where
         sz :: Bool#
    sz   = BigNat# -> Bool#
    wordArraySize# BigNat#
    a

         go :: Bool# -> Addr# -> State# s -> State# s
    go Bool#
    i Addr#
    adr State# s
    s
          | Bool#
    0# <- Bool#
    i
          = State# s
    s

          | Word#
    w <- BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a (Bool#
    i Bool# -> Bool# -> Bool#
    -# Bool#
    1#)
          = case Word# -> Addr# -> State# s -> State# s
    forall s. Word# -> Addr# -> State# s -> State# s
    wordWriteAddrBE# Word#
    w Addr#
    adr State# s
    s of
             State# s
    s' -> Bool# -> Addr# -> State# s -> State# s
    go (Bool#
    i Bool# -> Bool# -> Bool#
    -# Bool#
    1#)
                      (Addr#
    adr Addr# -> Bool# -> Addr#
    `plusAddr#` WORD_SIZE_IN_BYTES# ) s'

    -- | Write a BigNat in base-256 representation and return the
    -- number of bytes written.
    --
    -- The endianness is selected with the Bool# parameter: most significant
    -- byte first (big-endian) if @1#@ or least significant byte first
    -- (little-endian) if @0#@.
    --
    -- Use \"@'bigNatSizeInBase' 256# /i/@\" to compute the exact number of bytes
    -- written in advance. In case of @/i/ == 0@, the function will write and report
    -- zero bytes written.
    bigNatToAddr# :: BigNat# -> Addr# -> Bool# -> State# s -> (# State# s, Word# #)
    bigNatToAddr# :: forall s.
    BigNat# -> Addr# -> Bool# -> State# s -> (# State# s, Word# #)
    bigNatToAddr# BigNat#
    a Addr#
    addr Bool#
    0# State# s
    s = BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
    forall s. BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
    bigNatToAddrLE# BigNat#
    a Addr#
    addr State# s
    s
    bigNatToAddr# BigNat#
    a Addr#
    addr Bool#
    _  State# s
    s = BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
    forall s. BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
    bigNatToAddrBE# BigNat#
    a Addr#
    addr State# s
    s

    -- | Write a BigNat in base-256 representation and return the
    -- number of bytes written.
    --
    -- The endianness is selected with the Bool# parameter: most significant
    -- byte first (big-endian) if @1#@ or least significant byte first
    -- (little-endian) if @0#@.
    --
    -- Use \"@'bigNatSizeInBase' 256# /i/@\" to compute the exact number of bytes
    -- written in advance. In case of @/i/ == 0@, the function will write and report
    -- zero bytes written.
    bigNatToAddr :: BigNat# -> Addr# -> Bool# -> IO Word
    bigNatToAddr :: BigNat# -> Addr# -> Bool# -> IO Word
    bigNatToAddr BigNat#
    a Addr#
    addr Bool#
    e = (State# RealWorld -> (# State# RealWorld, Word #)) -> IO Word
    forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
    IO \State# RealWorld
    s -> case BigNat#
    -> Addr#
    -> Bool#
    -> State# RealWorld
    -> (# State# RealWorld, Word# #)
    forall s.
    BigNat# -> Addr# -> Bool# -> State# s -> (# State# s, Word# #)
    bigNatToAddr# BigNat#
    a Addr#
    addr Bool#
    e State# RealWorld
    s of
       (# State# RealWorld
    s', Word#
    w #) -> (# State# RealWorld
    s', Word# -> Word
    W# Word#
    w #)

    -------------------------------------------------
    -- Import from memory
    -------------------------------------------------

    -- | Read a BigNat in base-256 little-endian representation from an Addr#.
    --
    -- The size is given in bytes.
    --
    -- Higher limbs equal to 0 are automatically trimed.
    bigNatFromAddrLE# :: Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
    bigNatFromAddrLE# :: forall s. Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
    bigNatFromAddrLE# Word#
    0## Addr#
    _    State# s
    s = (# State# s
    s, Void# -> BigNat#
    bigNatZero# Void#
    void# #)
    bigNatFromAddrLE# Word#
    sz  Addr#
    addr State# s
    s =
       let
          !nw :: Word#
    nw = Word#
    sz Word# -> Bool# -> Word#
    `uncheckedShiftRL#` WORD_SIZE_BYTES_SHIFT#
          !nb :: Word#
    nb = Word#
    sz Word# -> Word# -> Word#
    `and#` WORD_SIZE_BYTES_MASK##

          readMSB :: MutableWordArray# s -> State# s -> State# s
    readMSB MutableWordArray# s
    mwa State# s
    s
             | Word#
    0## <- Word#
    nb
             = State# s
    s

             | Bool#
    off <- Word# -> Bool#
    word2Int# (Word#
    nw Word# -> Bool# -> Word#
    `uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#)
             = case Word# -> Addr# -> State# s -> (# State# s, Word# #)
    forall s. Word# -> Addr# -> State# s -> (# State# s, Word# #)
    wordFromAddrLE# Word#
    nb (Addr#
    addr Addr# -> Bool# -> Addr#
    `plusAddr#` Bool#
    off) State# s
    s of
                (# State# s
    s, Word#
    w #) -> MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# s
    mwa (Word# -> Bool#
    word2Int# Word#
    nw) Word#
    w State# s
    s

          go :: MutableWordArray# s -> Bool# -> State# s -> State# s
    go MutableWordArray# s
    mwa Bool#
    i State# s
    s
             | Bool# -> Bool
    isTrue# (Bool#
    i Bool# -> Bool# -> Bool#
    ==# Word# -> Bool#
    word2Int# Word#
    nw)
             = State# s
    s

             | Bool#
    off <- Bool#
    i Bool# -> Bool# -> Bool#
    `uncheckedIShiftL#` WORD_SIZE_BYTES_SHIFT#
             = case Word# -> Addr# -> State# s -> (# State# s, Word# #)
    forall s. Word# -> Addr# -> State# s -> (# State# s, Word# #)
    wordFromAddrLE# WORD_SIZE_IN_BYTES## (addr State# s
    `plusAddr#` off) s of
                (# State# s
    s, Word#
    w #) -> case MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# s
    mwa Bool#
    i Word#
    w State# s
    s of
                   State# s
    s -> MutableWordArray# s -> Bool# -> State# s -> State# s
    go MutableWordArray# s
    mwa (Bool#
    i Bool# -> Bool# -> Bool#
    +# Bool#
    1#) State# s
    s

       in case Bool# -> State# s -> (# State# s, MutableWordArray# s #)
    forall s. Bool# -> State# s -> (# State# s, MutableWordArray# s #)
    newWordArray# (Word# -> Bool#
    word2Int# Word#
    nw Bool# -> Bool# -> Bool#
    +# (Word# -> Bool#
    word2Int# Word#
    nb Bool# -> Bool# -> Bool#
    /=# Bool#
    0#)) State# s
    s of
             (# State# s
    s, MutableWordArray# s
    mwa #) -> case MutableWordArray# s -> State# s -> State# s
    forall s. MutableByteArray# s -> State# s -> State# s
    readMSB MutableWordArray# s
    mwa State# s
    s of
                State# s
    s -> case MutableWordArray# s -> Bool# -> State# s -> State# s
    forall {s}. MutableWordArray# s -> Bool# -> State# s -> State# s
    go MutableWordArray# s
    mwa Bool#
    0# State# s
    s of
                   State# s
    s -> case MutableWordArray# s -> State# s -> State# s
    forall s. MutableByteArray# s -> State# s -> State# s
    mwaTrimZeroes# MutableWordArray# s
    mwa State# s
    s of
                      State# s
    s -> MutableWordArray# s -> State# s -> (# State# s, BigNat# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, BigNat# #)
    unsafeFreezeByteArray# MutableWordArray# s
    mwa State# s
    s

    -- | Read a BigNat in base-256 big-endian representation from an Addr#.
    --
    -- The size is given in bytes.
    --
    -- Null higher limbs are automatically trimed.
    bigNatFromAddrBE# :: Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
    bigNatFromAddrBE# :: forall s. Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
    bigNatFromAddrBE# Word#
    0## Addr#
    _    State# s
    s = (# State# s
    s, Void# -> BigNat#
    bigNatZero# Void#
    void# #)
    bigNatFromAddrBE# Word#
    sz  Addr#
    addr State# s
    s =
       let
          !nw :: Bool#
    nw = Word# -> Bool#
    word2Int# (Word#
    sz Word# -> Bool# -> Word#
    `uncheckedShiftRL#` WORD_SIZE_BYTES_SHIFT#)
          !nb :: Word#
    nb = Word#
    sz Word# -> Word# -> Word#
    `and#` WORD_SIZE_BYTES_MASK##

          goMSB :: MutableWordArray# s -> State# s -> State# s
    goMSB MutableWordArray# s
    mwa State# s
    s
             | Word#
    0## <- Word#
    nb
             = State# s
    s

             | Bool
    True
             = case Word# -> Addr# -> State# s -> (# State# s, Word# #)
    forall s. Word# -> Addr# -> State# s -> (# State# s, Word# #)
    wordFromAddrBE# Word#
    nb Addr#
    addr State# s
    s of
                (# State# s
    s, Word#
    w #) -> MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# s
    mwa Bool#
    nw Word#
    w State# s
    s

          go :: MutableWordArray# s -> Bool# -> State# s -> State# s
    go MutableWordArray# s
    mwa Bool#
    i State# s
    s
             | Bool# -> Bool
    isTrue# (Bool#
    i Bool# -> Bool# -> Bool#
    ==# Bool#
    nw)
             = State# s
    s

             | Bool#
    k <- Bool#
    nw Bool# -> Bool# -> Bool#
    -# Bool#
    1# Bool# -> Bool# -> Bool#
    -# Bool#
    i
             , Bool#
    off <- (Bool#
    k Bool# -> Bool# -> Bool#
    `uncheckedIShiftL#` WORD_SIZE_BYTES_SHIFT#) +# word2Int# nb
             = case Word# -> Addr# -> State# s -> (# State# s, Word# #)
    forall s. Word# -> Addr# -> State# s -> (# State# s, Word# #)
    wordFromAddrBE# WORD_SIZE_IN_BYTES## (addr State# s
    `plusAddr#` off) s of
                (# State# s
    s, Word#
    w #) -> case MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# s
    mwa Bool#
    i Word#
    w State# s
    s of
                   State# s
    s -> MutableWordArray# s -> Bool# -> State# s -> State# s
    go MutableWordArray# s
    mwa (Bool#
    i Bool# -> Bool# -> Bool#
    +# Bool#
    1#) State# s
    s

       in case Bool# -> State# s -> (# State# s, MutableWordArray# s #)
    forall s. Bool# -> State# s -> (# State# s, MutableWordArray# s #)
    newWordArray# (Bool#
    nw Bool# -> Bool# -> Bool#
    +# (Word# -> Bool#
    word2Int# Word#
    nb Bool# -> Bool# -> Bool#
    /=# Bool#
    0#)) State# s
    s of
             (# State# s
    s, MutableWordArray# s
    mwa #) -> case MutableWordArray# s -> State# s -> State# s
    forall s. MutableByteArray# s -> State# s -> State# s
    goMSB MutableWordArray# s
    mwa State# s
    s of
                State# s
    s -> case MutableWordArray# s -> Bool# -> State# s -> State# s
    forall {s}. MutableWordArray# s -> Bool# -> State# s -> State# s
    go MutableWordArray# s
    mwa Bool#
    0# State# s
    s of
                   State# s
    s -> case MutableWordArray# s -> State# s -> State# s
    forall s. MutableByteArray# s -> State# s -> State# s
    mwaTrimZeroes# MutableWordArray# s
    mwa State# s
    s of
                      State# s
    s -> MutableWordArray# s -> State# s -> (# State# s, BigNat# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, BigNat# #)
    unsafeFreezeByteArray# MutableWordArray# s
    mwa State# s
    s

    -- | Read a BigNat in base-256 representation from an Addr#.
    --
    -- The size is given in bytes.
    --
    -- The endianness is selected with the Bool# parameter: most significant
    -- byte first (big-endian) if @1#@ or least significant byte first
    -- (little-endian) if @0#@.
    --
    -- Null higher limbs are automatically trimed.
    bigNatFromAddr# :: Word# -> Addr# -> Bool# -> State# s -> (# State# s, BigNat# #)
    bigNatFromAddr# :: forall s.
    Word# -> Addr# -> Bool# -> State# s -> (# State# s, BigNat# #)
    bigNatFromAddr# Word#
    sz Addr#
    addr Bool#
    0# State# s
    s = Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
    forall s. Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
    bigNatFromAddrLE# Word#
    sz Addr#
    addr State# s
    s
    bigNatFromAddr# Word#
    sz Addr#
    addr Bool#
    _  State# s
    s = Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
    forall s. Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
    bigNatFromAddrBE# Word#
    sz Addr#
    addr State# s
    s

    -------------------------------------------------
    -- Export to ByteArray
    -------------------------------------------------

    -- | Write a BigNat in base-256 little-endian representation and return the
    -- number of bytes written.
    --
    -- Use \"@'bigNatSizeInBase' 256# /i/@\" to compute the exact number of bytes
    -- written in advance. In case of @/i/ == 0@, the function will write and report
    -- zero bytes written.
    bigNatToMutableByteArrayLE# :: BigNat# -> MutableByteArray# s -> Word# -> State# s -> (# State# s, Word# #)
    bigNatToMutableByteArrayLE# :: forall s.
    BigNat#
    -> MutableByteArray# s
    -> Word#
    -> State# s
    -> (# State# s, Word# #)
    bigNatToMutableByteArrayLE# BigNat#
    a MutableByteArray# s
    mba Word#
    moff State# s
    s0
       | Bool# -> Bool
    isTrue# (Bool#
    sz Bool# -> Bool# -> Bool#
    ==# Bool#
    0#) = (# State# s
    s0, Word#
    0## #)
       | Bool
    True = case State# s -> (# State# s, Word# #)
    writeMSB State# s
    s0 of
          (# State# s
    s1, Word#
    k #) -> case Bool# -> State# s -> State# s
    go Bool#
    0# State# s
    s1 of
             State# s
    s2 -> (# State# s
    s2, Word#
    k Word# -> Word# -> Word#
    `plusWord#` (Bool# -> Word#
    int2Word# Bool#
    li Word# -> Bool# -> Word#
    `uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#) #)
       where
         !sz :: Bool#
    sz = BigNat# -> Bool#
    wordArraySize# BigNat#
    a
         !li :: Bool#
    li = Bool#
    sz Bool# -> Bool# -> Bool#
    -# Bool#
    1#

         writeMSB :: State# s -> (# State# s, Word# #)
    writeMSB = Word#
    -> MutableByteArray# s
    -> Word#
    -> State# s
    -> (# State# s, Word# #)
    forall s.
    Word#
    -> MutableByteArray# s
    -> Word#
    -> State# s
    -> (# State# s, Word# #)
    wordToMutableByteArrayLE# (BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a Bool#
    li)
                      MutableByteArray# s
    mba (Word#
    moff Word# -> Word# -> Word#
    `plusWord#` Bool# -> Word#
    int2Word# (Bool#
    li Bool# -> Bool# -> Bool#
    `uncheckedIShiftL#` WORD_SIZE_BYTES_SHIFT#))

         go :: Bool# -> State# s -> State# s
    go Bool#
    i State# s
    s
          | Bool# -> Bool
    isTrue# (Bool#
    i Bool# -> Bool# -> Bool#
    <# Bool#
    li)
          , Word#
    off <- Bool# -> Word#
    int2Word# Bool#
    i Word# -> Bool# -> Word#
    `uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#
          , Word#
    w <- BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a Bool#
    i
          = case Word# -> MutableByteArray# s -> Word# -> State# s -> State# s
    forall s.
    Word# -> MutableByteArray# s -> Word# -> State# s -> State# s
    wordWriteMutableByteArrayLE# Word#
    w MutableByteArray# s
    mba (Word#
    moff Word# -> Word# -> Word#
    `plusWord#` Word#
    off) State# s
    s of
             State# s
    s -> Bool# -> State# s -> State# s
    go (Bool#
    i Bool# -> Bool# -> Bool#
    +# Bool#
    1#) State# s
    s

          | Bool
    True
          = State# s
    s

    -- | Write a BigNat in base-256 big-endian representation and return the
    -- number of bytes written.
    --
    -- Use \"@'bigNatSizeInBase' 256# /i/@\" to compute the exact number of bytes
    -- written in advance. In case of @/i/ == 0@, the function will write and report
    -- zero bytes written.
    bigNatToMutableByteArrayBE# :: BigNat# -> MutableByteArray# s -> Word# -> State# s -> (# State# s, Word# #)
    bigNatToMutableByteArrayBE# :: forall s.
    BigNat#
    -> MutableByteArray# s
    -> Word#
    -> State# s
    -> (# State# s, Word# #)
    bigNatToMutableByteArrayBE# BigNat#
    a MutableByteArray# s
    mba Word#
    moff State# s
    s0
       | Bool# -> Bool
    isTrue# (Bool#
    sz Bool# -> Bool# -> Bool#
    ==# Bool#
    0#) = (# State# s
    s0, Word#
    0## #)
       | Word#
    msw <- BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a (Bool#
    sz Bool# -> Bool# -> Bool#
    -# Bool#
    1#)
       = case Word#
    -> MutableByteArray# s
    -> Word#
    -> State# s
    -> (# State# s, Word# #)
    forall s.
    Word#
    -> MutableByteArray# s
    -> Word#
    -> State# s
    -> (# State# s, Word# #)
    wordToMutableByteArrayBE# Word#
    msw MutableByteArray# s
    mba Word#
    moff State# s
    s0 of
          (# State# s
    s1, Word#
    k #) -> case Bool# -> Word# -> State# s -> State# s
    go (Bool#
    sz Bool# -> Bool# -> Bool#
    -# Bool#
    1#) Word#
    k State# s
    s1 of
             State# s
    s2 -> (# State# s
    s2, Word#
    k Word# -> Word# -> Word#
    `plusWord#` (Bool# -> Word#
    int2Word# (Bool#
    sz Bool# -> Bool# -> Bool#
    -# Bool#
    1#) Word# -> Bool# -> Word#
    `uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#) #)
       where
         sz :: Bool#
    sz   = BigNat# -> Bool#
    wordArraySize# BigNat#
    a

         go :: Bool# -> Word# -> State# s -> State# s
    go Bool#
    i Word#
    c State# s
    s
          | Bool#
    0# <- Bool#
    i
          = State# s
    s

          | Word#
    w <- BigNat# -> Bool# -> Word#
    indexWordArray# BigNat#
    a (Bool#
    i Bool# -> Bool# -> Bool#
    -# Bool#
    1#)
          = case Word# -> MutableByteArray# s -> Word# -> State# s -> State# s
    forall s.
    Word# -> MutableByteArray# s -> Word# -> State# s -> State# s
    wordWriteMutableByteArrayBE# Word#
    w MutableByteArray# s
    mba (Word#
    moff Word# -> Word# -> Word#
    `plusWord#` Word#
    c) State# s
    s of
             State# s
    s' -> Bool# -> Word# -> State# s -> State# s
    go (Bool#
    i Bool# -> Bool# -> Bool#
    -# Bool#
    1#)
                      (Word#
    c Word# -> Word# -> Word#
    `plusWord#` WORD_SIZE_IN_BYTES## ) s'

    -- | Write a BigNat in base-256 representation and return the
    -- number of bytes written.
    --
    -- The endianness is selected with the Bool# parameter: most significant
    -- byte first (big-endian) if @1#@ or least significant byte first
    -- (little-endian) if @0#@.
    --
    -- Use \"@'bigNatSizeInBase' 256# /i/@\" to compute the exact number of bytes
    -- written in advance. In case of @/i/ == 0@, the function will write and report
    -- zero bytes written.
    bigNatToMutableByteArray# :: BigNat# -> MutableByteArray# s -> Word# -> Bool# -> State# s -> (# State# s, Word# #)
    bigNatToMutableByteArray# :: forall s.
    BigNat#
    -> MutableByteArray# s
    -> Word#
    -> Bool#
    -> State# s
    -> (# State# s, Word# #)
    bigNatToMutableByteArray# BigNat#
    a MutableByteArray# s
    mba Word#
    off Bool#
    0# State# s
    s = BigNat#
    -> MutableByteArray# s
    -> Word#
    -> State# s
    -> (# State# s, Word# #)
    forall s.
    BigNat#
    -> MutableByteArray# s
    -> Word#
    -> State# s
    -> (# State# s, Word# #)
    bigNatToMutableByteArrayLE# BigNat#
    a MutableByteArray# s
    mba Word#
    off State# s
    s
    bigNatToMutableByteArray# BigNat#
    a MutableByteArray# s
    mba Word#
    off Bool#
    _  State# s
    s = BigNat#
    -> MutableByteArray# s
    -> Word#
    -> State# s
    -> (# State# s, Word# #)
    forall s.
    BigNat#
    -> MutableByteArray# s
    -> Word#
    -> State# s
    -> (# State# s, Word# #)
    bigNatToMutableByteArrayBE# BigNat#
    a MutableByteArray# s
    mba Word#
    off State# s
    s

    -------------------------------------------------
    -- Import from ByteArray
    -------------------------------------------------

    -- | Read a BigNat in base-256 little-endian representation from a ByteArray#.
    --
    -- The size is given in bytes.
    --
    -- Null higher limbs are automatically trimed.
    bigNatFromByteArrayLE# :: Word# -> ByteArray# -> Word# -> State# s -> (# State# s, BigNat# #)
    bigNatFromByteArrayLE# :: forall s.
    Word# -> BigNat# -> Word# -> State# s -> (# State# s, BigNat# #)
    bigNatFromByteArrayLE# Word#
    0## BigNat#
    _  Word#
    _    State# s
    s = (# State# s
    s, Void# -> BigNat#
    bigNatZero# Void#
    void# #)
    bigNatFromByteArrayLE# Word#
    sz  BigNat#
    ba Word#
    moff State# s
    s =
       let
          !nw :: Word#
    nw = Word#
    sz Word# -> Bool# -> Word#
    `uncheckedShiftRL#` WORD_SIZE_BYTES_SHIFT#
          !nb :: Word#
    nb = Word#
    sz Word# -> Word# -> Word#
    `and#` WORD_SIZE_BYTES_MASK##

          readMSB :: MutableWordArray# s -> State# s -> State# s
    readMSB MutableWordArray# s
    mwa State# s
    s
             | Word#
    0## <- Word#
    nb
             = State# s
    s

             | Word#
    off <- Word#
    nw Word# -> Bool# -> Word#
    `uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#
             = case Word# -> BigNat# -> Word# -> Word#
    wordFromByteArrayLE# Word#
    nb BigNat#
    ba (Word#
    moff Word# -> Word# -> Word#
    `plusWord#` Word#
    off) of
                   Word#
    w -> MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# s
    mwa (Word# -> Bool#
    word2Int# Word#
    nw) Word#
    w State# s
    s

          go :: MutableWordArray# s -> Word# -> State# s -> State# s
    go MutableWordArray# s
    mwa Word#
    i State# s
    s
             | Bool# -> Bool
    isTrue# (Word#
    i Word# -> Word# -> Bool#
    `eqWord#` Word#
    nw)
             = State# s
    s

             | Word#
    off <- Word#
    i Word# -> Bool# -> Word#
    `uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#
             = case Word# -> BigNat# -> Word# -> Word#
    wordFromByteArrayLE# WORD_SIZE_IN_BYTES## ba (moff `plusWord#` off) of
                   Word#
    w -> case MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# s
    mwa (Word# -> Bool#
    word2Int# Word#
    i) Word#
    w State# s
    s of
                      State# s
    s -> MutableWordArray# s -> Word# -> State# s -> State# s
    go MutableWordArray# s
    mwa (Word#
    i Word# -> Word# -> Word#
    `plusWord#` Word#
    1##) State# s
    s

       in case Bool# -> State# s -> (# State# s, MutableWordArray# s #)
    forall s. Bool# -> State# s -> (# State# s, MutableWordArray# s #)
    newWordArray# (Word# -> Bool#
    word2Int# Word#
    nw Bool# -> Bool# -> Bool#
    +# (Word# -> Bool#
    word2Int# Word#
    nb Bool# -> Bool# -> Bool#
    /=# Bool#
    0#)) State# s
    s of
             (# State# s
    s, MutableWordArray# s
    mwa #) -> case MutableWordArray# s -> State# s -> State# s
    forall s. MutableByteArray# s -> State# s -> State# s
    readMSB MutableWordArray# s
    mwa State# s
    s of
                State# s
    s -> case MutableWordArray# s -> Word# -> State# s -> State# s
    forall {s}. MutableWordArray# s -> Word# -> State# s -> State# s
    go MutableWordArray# s
    mwa Word#
    0## State# s
    s of
                   State# s
    s -> case MutableWordArray# s -> State# s -> State# s
    forall s. MutableByteArray# s -> State# s -> State# s
    mwaTrimZeroes# MutableWordArray# s
    mwa State# s
    s of
                      State# s
    s -> MutableWordArray# s -> State# s -> (# State# s, BigNat# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, BigNat# #)
    unsafeFreezeByteArray# MutableWordArray# s
    mwa State# s
    s

    -- | Read a BigNat in base-256 big-endian representation from a ByteArray#.
    --
    -- The size is given in bytes.
    --
    -- Null higher limbs are automatically trimed.
    bigNatFromByteArrayBE# :: Word# -> ByteArray# -> Word# -> State# s -> (# State# s, BigNat# #)
    bigNatFromByteArrayBE# :: forall s.
    Word# -> BigNat# -> Word# -> State# s -> (# State# s, BigNat# #)
    bigNatFromByteArrayBE# Word#
    0## BigNat#
    _  Word#
    _    State# s
    s = (# State# s
    s, Void# -> BigNat#
    bigNatZero# Void#
    void# #)
    bigNatFromByteArrayBE# Word#
    sz  BigNat#
    ba Word#
    moff State# s
    s =
       let
          !nw :: Word#
    nw = Word#
    sz Word# -> Bool# -> Word#
    `uncheckedShiftRL#` WORD_SIZE_BYTES_SHIFT#
          !nb :: Word#
    nb = Word#
    sz Word# -> Word# -> Word#
    `and#` WORD_SIZE_BYTES_MASK##

          goMSB :: MutableWordArray# s -> State# s -> State# s
    goMSB MutableWordArray# s
    mwa State# s
    s
             | Word#
    0## <- Word#
    nb
             = State# s
    s

             | Bool
    True
             = case Word# -> BigNat# -> Word# -> Word#
    wordFromByteArrayBE# Word#
    nb BigNat#
    ba Word#
    moff of
                Word#
    w -> MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# s
    mwa (Word# -> Bool#
    word2Int# Word#
    nw) Word#
    w State# s
    s

          go :: MutableWordArray# s -> Word# -> State# s -> State# s
    go MutableWordArray# s
    mwa Word#
    i State# s
    s
             | Bool# -> Bool
    isTrue# (Word#
    i Word# -> Word# -> Bool#
    `eqWord#` Word#
    nw)
             = State# s
    s

             | Word#
    k <- Word#
    nw Word# -> Word# -> Word#
    `minusWord#` Word#
    1## Word# -> Word# -> Word#
    `minusWord#` Word#
    i
             , Word#
    off <- (Word#
    k Word# -> Bool# -> Word#
    `uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#) `plusWord#` nb
             = case Word# -> BigNat# -> Word# -> Word#
    wordFromByteArrayBE# WORD_SIZE_IN_BYTES## ba (moff `plusWord#` off) of
                Word#
    w -> case MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    forall s.
    MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
    mwaWrite# MutableWordArray# s
    mwa (Word# -> Bool#
    word2Int# Word#
    i) Word#
    w State# s
    s of
                   State# s
    s -> MutableWordArray# s -> Word# -> State# s -> State# s
    go MutableWordArray# s
    mwa (Word#
    i Word# -> Word# -> Word#
    `plusWord#` Word#
    1##) State# s
    s

       in case Bool# -> State# s -> (# State# s, MutableWordArray# s #)
    forall s. Bool# -> State# s -> (# State# s, MutableWordArray# s #)
    newWordArray# (Word# -> Bool#
    word2Int# Word#
    nw Bool# -> Bool# -> Bool#
    +# (Word# -> Bool#
    word2Int# Word#
    nb Bool# -> Bool# -> Bool#
    /=# Bool#
    0#)) State# s
    s of
             (# State# s
    s, MutableWordArray# s
    mwa #) -> case MutableWordArray# s -> State# s -> State# s
    forall s. MutableByteArray# s -> State# s -> State# s
    goMSB MutableWordArray# s
    mwa State# s
    s of
                State# s
    s -> case MutableWordArray# s -> Word# -> State# s -> State# s
    forall {s}. MutableWordArray# s -> Word# -> State# s -> State# s
    go MutableWordArray# s
    mwa Word#
    0## State# s
    s of
                   State# s
    s -> case MutableWordArray# s -> State# s -> State# s
    forall s. MutableByteArray# s -> State# s -> State# s
    mwaTrimZeroes# MutableWordArray# s
    mwa State# s
    s of
                      State# s
    s -> MutableWordArray# s -> State# s -> (# State# s, BigNat# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, BigNat# #)
    unsafeFreezeByteArray# MutableWordArray# s
    mwa State# s
    s

    -- | Read a BigNat in base-256 representation from a ByteArray#.
    --
    -- The size is given in bytes.
    --
    -- The endianness is selected with the Bool# parameter: most significant
    -- byte first (big-endian) if @1#@ or least significant byte first
    -- (little-endian) if @0#@.
    --
    -- Null higher limbs are automatically trimed.
    bigNatFromByteArray# :: Word# -> ByteArray# -> Word# -> Bool# -> State# s -> (# State# s, BigNat# #)
    bigNatFromByteArray# :: forall s.
    Word#
    -> BigNat# -> Word# -> Bool# -> State# s -> (# State# s, BigNat# #)
    bigNatFromByteArray# Word#
    sz BigNat#
    ba Word#
    off Bool#
    0# State# s
    s = Word# -> BigNat# -> Word# -> State# s -> (# State# s, BigNat# #)
    forall s.
    Word# -> BigNat# -> Word# -> State# s -> (# State# s, BigNat# #)
    bigNatFromByteArrayLE# Word#
    sz BigNat#
    ba Word#
    off State# s
    s
    bigNatFromByteArray# Word#
    sz BigNat#
    ba Word#
    off Bool#
    _  State# s
    s = Word# -> BigNat# -> Word# -> State# s -> (# State# s, BigNat# #)
    forall s.
    Word# -> BigNat# -> Word# -> State# s -> (# State# s, BigNat# #)
    bigNatFromByteArrayBE# Word#
    sz BigNat#
    ba Word#
    off State# s
    s

    -- | Create a BigNat# from a WordArray# containing /n/ limbs in
    -- least-significant-first order.
    --
    -- If possible 'WordArray#', will be used directly (i.e. shared
    -- /without/ cloning the 'WordArray#' into a newly allocated one)
    bigNatFromWordArray# :: WordArray# -> Word# -> BigNat#
    bigNatFromWordArray# :: BigNat# -> Word# -> BigNat#
    bigNatFromWordArray# BigNat#
    wa Word#
    n0
       | Bool# -> Bool
    isTrue# (Word#
    n Word# -> Word# -> Bool#
    `eqWord#` Word#
    0##)
       = Void# -> BigNat#
    bigNatZero# Void#
    void#

       | Bool# -> Bool
    isTrue# (Word#
    r Word# -> Word# -> Bool#
    `eqWord#` Word#
    0##) -- i.e. wa is multiple of limb-size
       , Bool# -> Bool
    isTrue# (Word#
    q Word# -> Word# -> Bool#
    `eqWord#` Word#
    n)
       = BigNat#
    wa

       | Bool
    True = Bool#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> BigNat#
    withNewWordArray# (Word# -> Bool#
    word2Int# Word#
    n) \MutableWordArray# RealWorld
    mwa State# RealWorld
    s ->
                   MutableWordArray# RealWorld
    -> Bool#
    -> BigNat#
    -> Bool#
    -> Bool#
    -> State# RealWorld
    -> State# RealWorld
    forall s.
    MutableByteArray# s
    -> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
    mwaArrayCopy# MutableWordArray# RealWorld
    mwa Bool#
    0# BigNat#
    wa Bool#
    0# (Word# -> Bool#
    word2Int# Word#
    n) State# RealWorld
    s
       where
          !(# Word#
    q, Word#
    r #) = Word# -> Word# -> (# Word#, Word# #)
    quotRemWord# (Bool# -> Word#
    int2Word# (BigNat# -> Bool#
    sizeofByteArray# BigNat#
    wa))
                                     WORD_SIZE_IN_BYTES##
          -- find real size in Words by removing trailing null limbs
          !n :: Word#
    n = Word# -> Word#
    real_size Word#
    n0
          real_size :: Word# -> Word#
    real_size Word#
    0## = Word#
    0##
          real_size Word#
    i
               | Word#
    0## <- BigNat# -> Bool# -> Word#
    bigNatIndex# BigNat#
    wa (Word# -> Bool#
    word2Int# (Word#
    i Word# -> Word# -> Word#
    `minusWord#` Word#
    1##))
               = Word# -> Word#
    real_size (Word#
    i Word# -> Word# -> Word#
    `minusWord#` Word#
    1##)
          real_size Word#
    i = Word#
    i

    -- | Create a BigNat from a WordArray# containing /n/ limbs in
    -- least-significant-first order.
    --
    -- If possible 'WordArray#', will be used directly (i.e. shared
    -- /without/ cloning the 'WordArray#' into a newly allocated one)
    bigNatFromWordArray :: WordArray# -> Word# -> BigNat
    bigNatFromWordArray :: BigNat# -> Word# -> BigNat
    bigNatFromWordArray BigNat#
    wa Word#
    n = BigNat# -> BigNat
    BN# (BigNat# -> Word# -> BigNat#
    bigNatFromWordArray# BigNat#
    wa Word#
    n)

    -------------------------------------------------
    -- Instances
    -------------------------------------------------

    instance Eq BigNat where
       BN# BigNat#
    a == :: BigNat -> BigNat -> Bool
    == BN# BigNat#
    b = BigNat# -> BigNat# -> Bool
    bigNatEq BigNat#
    a BigNat#
    b
       BN# BigNat#
    a /= :: BigNat -> BigNat -> Bool
    /= BN# BigNat#
    b = BigNat# -> BigNat# -> Bool
    bigNatNe BigNat#
    a BigNat#
    b

    instance Ord BigNat where
       (BN# BigNat#
    a) compare :: BigNat -> BigNat -> Ordering
    `compare` (BN# BigNat#
    b) = BigNat# -> BigNat# -> Ordering
    bigNatCompare BigNat#
    a BigNat#
    b
       BN# BigNat#
    a < :: BigNat -> BigNat -> Bool
    <  BN# BigNat#
    b = BigNat# -> BigNat# -> Bool
    bigNatLt BigNat#
    a BigNat#
    b
       BN# BigNat#
    a <= :: BigNat -> BigNat -> Bool
    <= BN# BigNat#
    b = BigNat# -> BigNat# -> Bool
    bigNatLe BigNat#
    a BigNat#
    b
       BN# BigNat#
    a > :: BigNat -> BigNat -> Bool
    >  BN# BigNat#
    b = BigNat# -> BigNat# -> Bool
    bigNatGt BigNat#
    a BigNat#
    b
       BN# BigNat#
    a >= :: BigNat -> BigNat -> Bool
    >= BN# BigNat#
    b = BigNat# -> BigNat# -> Bool
    bigNatGe BigNat#
    a BigNat#
    b