    {-# LANGUAGE NoImplicitPrelude #-}
    {-# LANGUAGE BangPatterns #-}
    {-# LANGUAGE CPP #-}
    {-# LANGUAGE DeriveDataTypeable #-}
    {-# LANGUAGE GHCForeignImportPrim #-}
    {-# LANGUAGE MagicHash #-}
    {-# LANGUAGE UnboxedTuples #-}
    {-# LANGUAGE UnliftedFFITypes #-}
    {-# LANGUAGE NegativeLiterals #-}
    {-# LANGUAGE BlockArguments #-}
    {-# LANGUAGE LambdaCase #-}

    {-# OPTIONS_GHC -Wno-name-shadowing #-}

    -- | Backend based on the GNU GMP library.
    --
    -- This has been adapted from the legacy `integer-gmp` package written by
    -- Herbert Valerio Riedel.
    module GHC.Num.Backend.GMP where

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

    import GHC.Num.WordArray
    import GHC.Num.Primitives
    import GHC.Prim
    import GHC.Types
    import GHC.Magic (runRW#)
    import {-# SOURCE #-} GHC.Num.Integer
    import {-# SOURCE #-} GHC.Num.BigNat
    import {-# SOURCE #-} GHC.Num.Natural

    -- See W1 of Note [Tracking dependencies on primitives] in GHC.Internal.Base
    -- (This module uses the empty tuple () and string literals.)
    import GHC.Tuple ()
    import GHC.CString ()

    default ()

    -- | ghc-bignum backend name
    backendName :: [Char]
    backendName :: [Char]
    backendName = [Char]
    "gmp"

    ----------------------------------------------------------------------------
    -- type definitions

    -- NB: all code assumes GMP_LIMB_BITS == WORD_SIZE_IN_BITS
    -- The C99 code in cbits/gmp_wrappers.c will fail to compile if this doesn't hold

    -- | Type representing a GMP Limb
    type GmpLimb = Word -- actually, 'CULong'
    type GmpLimb# = Word#

    -- | Count of 'GmpLimb's, must be positive (unless specified otherwise).
    type GmpSize = Int  -- actually, a 'CLong'
    type GmpSize# = Int#

    narrowGmpSize# :: Int# -> Int#
    #if SIZEOF_LONG == SIZEOF_HSWORD
    narrowGmpSize# :: Int# -> Int#
    narrowGmpSize# Int#
    x = Int#
    x
    #elif (SIZEOF_LONG == 4) && (SIZEOF_HSWORD == 8)
    -- On IL32P64 (i.e. Win64), we have to be careful with CLong not being
    -- 64bit.  This is mostly an issue on values returned from C functions
    -- due to sign-extension.
    narrowGmpSize# = narrow32Int#
    #endif

    narrowCInt# :: Int# -> Int#
    narrowCInt# :: Int# -> Int#
    narrowCInt# = Int# -> Int#
    narrow32Int#

    bignat_compare :: WordArray# -> WordArray# -> Int#
    bignat_compare :: WordArray# -> WordArray# -> Int#
    bignat_compare WordArray#
    x WordArray#
    y = Int# -> Int#
    narrowCInt# (WordArray# -> WordArray# -> Int# -> Int#
    c_mpn_cmp WordArray#
    x WordArray#
    y (WordArray# -> Int#
    wordArraySize# WordArray#
    x))

    bignat_add
       :: MutableWordArray# RealWorld
       -> WordArray#
       -> WordArray#
       -> State# RealWorld
       -> State# RealWorld
    {-# INLINE bignat_add #-}
    bignat_add :: MutableWordArray# RealWorld
    -> WordArray# -> WordArray# -> State# RealWorld -> State# RealWorld
    bignat_add MutableWordArray# RealWorld
    mwa WordArray#
    wa WordArray#
    wb State# RealWorld
    s
       -- weird GMP requirement: the biggest comes first
       | Int# -> Bool
    isTrue# (WordArray# -> Int#
    wordArraySize# WordArray#
    wb Int# -> Int# -> Int#
    ># WordArray# -> Int#
    wordArraySize# WordArray#
    wa)
       = case IO Word -> State# RealWorld -> (# State# RealWorld, Word# #)
    ioWord# (MutableWordArray# RealWorld
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO Word
    forall s.
    MutableByteArray# s
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO Word
    c_mpn_add MutableWordArray# RealWorld
    mwa WordArray#
    wb (WordArray# -> Int#
    wordArraySize# WordArray#
    wb) WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa)) State# RealWorld
    s of
          (# State# RealWorld
    s', Word#
    c #) -> MutableWordArray# RealWorld
    -> Word# -> State# RealWorld -> State# RealWorld
    forall s. MutableWordArray# s -> Word# -> State# s -> State# s
    mwaWriteMostSignificant MutableWordArray# RealWorld
    mwa Word#
    c State# RealWorld
    s'

       | Bool
    True
       = case IO Word -> State# RealWorld -> (# State# RealWorld, Word# #)
    ioWord# (MutableWordArray# RealWorld
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO Word
    forall s.
    MutableByteArray# s
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO Word
    c_mpn_add MutableWordArray# RealWorld
    mwa WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) WordArray#
    wb (WordArray# -> Int#
    wordArraySize# WordArray#
    wb)) State# RealWorld
    s of
          (# State# RealWorld
    s', Word#
    c #) -> MutableWordArray# RealWorld
    -> Word# -> State# RealWorld -> State# RealWorld
    forall s. MutableWordArray# s -> Word# -> State# s -> State# s
    mwaWriteMostSignificant MutableWordArray# RealWorld
    mwa Word#
    c State# RealWorld
    s'

    bignat_add_word
       :: MutableWordArray# RealWorld
       -> WordArray#
       -> Word#
       -> State# RealWorld
       -> State# RealWorld
    {-# INLINE bignat_add_word #-}
    bignat_add_word :: MutableWordArray# RealWorld
    -> WordArray# -> Word# -> State# RealWorld -> State# RealWorld
    bignat_add_word MutableWordArray# RealWorld
    mwa WordArray#
    wa Word#
    b State# RealWorld
    s = do
       case IO Word -> State# RealWorld -> (# State# RealWorld, Word# #)
    ioWord# (MutableWordArray# RealWorld
    -> WordArray# -> Int# -> Word# -> IO Word
    forall s.
    MutableByteArray# s -> WordArray# -> Int# -> Word# -> IO Word
    c_mpn_add_1 MutableWordArray# RealWorld
    mwa WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) Word#
    b) State# RealWorld
    s of
          (# State# RealWorld
    s', Word#
    c #) -> MutableWordArray# RealWorld
    -> Word# -> State# RealWorld -> State# RealWorld
    forall s. MutableWordArray# s -> Word# -> State# s -> State# s
    mwaWriteMostSignificant MutableWordArray# RealWorld
    mwa Word#
    c State# RealWorld
    s'

    bignat_sub
       :: MutableWordArray# RealWorld
       -> WordArray#
       -> WordArray#
       -> State# RealWorld
       -> (# State# RealWorld, Bool# #)
    {-# INLINE bignat_sub #-}
    bignat_sub :: MutableWordArray# RealWorld
    -> WordArray#
    -> WordArray#
    -> State# RealWorld
    -> (# State# RealWorld, Int# #)
    bignat_sub MutableWordArray# RealWorld
    mwa WordArray#
    wa WordArray#
    wb State# RealWorld
    s =
       case IO Word -> State# RealWorld -> (# State# RealWorld, Word# #)
    ioWord# (MutableWordArray# RealWorld
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO Word
    forall s.
    MutableByteArray# s
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO Word
    c_mpn_sub MutableWordArray# RealWorld
    mwa WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) WordArray#
    wb (WordArray# -> Int#
    wordArraySize# WordArray#
    wb)) State# RealWorld
    s of
          (# State# RealWorld
    s', Word#
    1## #) -> (# State# RealWorld
    s', Int#
    0# #) -- underflow
          (# State# RealWorld
    s', Word#
    _   #) -> (# State# RealWorld
    s', Int#
    1# #) -- no underflow

    bignat_sub_word
       :: MutableWordArray# RealWorld
       -> WordArray#
       -> Word#
       -> State# RealWorld
       -> (# State# RealWorld, Bool# #)
    {-# INLINE bignat_sub_word #-}
    bignat_sub_word :: MutableWordArray# RealWorld
    -> WordArray#
    -> Word#
    -> State# RealWorld
    -> (# State# RealWorld, Int# #)
    bignat_sub_word MutableWordArray# RealWorld
    mwa WordArray#
    wa Word#
    b State# RealWorld
    s =
       case IO Word -> State# RealWorld -> (# State# RealWorld, Word# #)
    ioWord# (MutableWordArray# RealWorld
    -> WordArray# -> Int# -> Word# -> IO Word
    forall s.
    MutableByteArray# s -> WordArray# -> Int# -> Word# -> IO Word
    c_mpn_sub_1 MutableWordArray# RealWorld
    mwa WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) Word#
    b) State# RealWorld
    s of
          (# State# RealWorld
    s', Word#
    1## #) -> (# State# RealWorld
    s', Int#
    0# #) -- underflow
          (# State# RealWorld
    s', Word#
    _   #) -> (# State# RealWorld
    s', Int#
    1# #) -- no underflow

    bignat_mul
       :: MutableWordArray# RealWorld
       -> WordArray#
       -> WordArray#
       -> State# RealWorld
       -> State# RealWorld
    {-# INLINE bignat_mul #-}
    bignat_mul :: MutableWordArray# RealWorld
    -> WordArray# -> WordArray# -> State# RealWorld -> State# RealWorld
    bignat_mul MutableWordArray# RealWorld
    mwa WordArray#
    wa WordArray#
    wb State# RealWorld
    s = do
       case IO Word -> State# RealWorld -> (# State# RealWorld, Word# #)
    ioWord# (MutableWordArray# RealWorld
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO Word
    forall s.
    MutableByteArray# s
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO Word
    c_mpn_mul MutableWordArray# RealWorld
    mwa WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) WordArray#
    wb (WordArray# -> Int#
    wordArraySize# WordArray#
    wb)) State# RealWorld
    s of
          (# State# RealWorld
    s', Word#
    _msl #) -> State# RealWorld
    s' -- we don't care about the most-significant
                               -- limb. The caller shrink the mwa if
                               -- necessary anyway.

    bignat_mul_word
       :: MutableWordArray# RealWorld -- ^ Result
       -> WordArray#
       -> Word#
       -> State# RealWorld
       -> State# RealWorld
    {-# INLINE bignat_mul_word #-}
    bignat_mul_word :: MutableWordArray# RealWorld
    -> WordArray# -> Word# -> State# RealWorld -> State# RealWorld
    bignat_mul_word MutableWordArray# RealWorld
    mwa WordArray#
    wa Word#
    b State# RealWorld
    s =
       case IO Word -> State# RealWorld -> (# State# RealWorld, Word# #)
    ioWord# (MutableWordArray# RealWorld
    -> WordArray# -> Int# -> Word# -> IO Word
    forall s.
    MutableByteArray# s -> WordArray# -> Int# -> Word# -> IO Word
    c_mpn_mul_1 MutableWordArray# RealWorld
    mwa WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) Word#
    b) State# RealWorld
    s of
          (# State# RealWorld
    s', Word#
    c #) -> MutableWordArray# RealWorld
    -> Word# -> State# RealWorld -> State# RealWorld
    forall s. MutableWordArray# s -> Word# -> State# s -> State# s
    mwaWriteMostSignificant MutableWordArray# RealWorld
    mwa Word#
    c State# RealWorld
    s'

    bignat_popcount :: WordArray# -> Word#
    {-# INLINE bignat_popcount #-}
    bignat_popcount :: WordArray# -> Word#
    bignat_popcount WordArray#
    wa = WordArray# -> Int# -> Word#
    c_mpn_popcount WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa)

    bignat_shiftl
       :: MutableWordArray# RealWorld
       -> WordArray#
       -> Word#
       -> State# RealWorld
       -> State# RealWorld
    {-# INLINE bignat_shiftl #-}
    bignat_shiftl :: MutableWordArray# RealWorld
    -> WordArray# -> Word# -> State# RealWorld -> State# RealWorld
    bignat_shiftl MutableWordArray# RealWorld
    mwa WordArray#
    wa Word#
    n State# RealWorld
    s =
       case IO Word -> State# RealWorld -> (# State# RealWorld, Word# #)
    ioWord# (MutableWordArray# RealWorld
    -> WordArray# -> Int# -> Word# -> IO Word
    forall s.
    MutableByteArray# s -> WordArray# -> Int# -> Word# -> IO Word
    c_mpn_lshift MutableWordArray# RealWorld
    mwa WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) Word#
    n) State# RealWorld
    s of
          (# State# RealWorld
    s', Word#
    _msl #) -> State# RealWorld
    s' -- we don't care about the most-significant
                               -- limb. The caller shrink the mwa if
                               -- necessary anyway.

    bignat_shiftr
       :: MutableWordArray# RealWorld
       -> WordArray#
       -> Word#
       -> State# RealWorld
       -> State# RealWorld
    {-# INLINE bignat_shiftr #-}
    bignat_shiftr :: MutableWordArray# RealWorld
    -> WordArray# -> Word# -> State# RealWorld -> State# RealWorld
    bignat_shiftr MutableWordArray# RealWorld
    mwa WordArray#
    wa Word#
    n State# RealWorld
    s =
       case IO Word -> State# RealWorld -> (# State# RealWorld, Word# #)
    ioWord# (MutableWordArray# RealWorld
    -> WordArray# -> Int# -> Word# -> IO Word
    forall s.
    MutableByteArray# s -> WordArray# -> Int# -> Word# -> IO Word
    c_mpn_rshift MutableWordArray# RealWorld
    mwa WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) Word#
    n) State# RealWorld
    s of
          (# State# RealWorld
    s', Word#
    _msl #) -> State# RealWorld
    s' -- we don't care about the most-significant
                               -- limb. The caller shrink the mwa if
                               -- necessary anyway.

    bignat_or
       :: MutableWordArray# RealWorld
       -> WordArray#
       -> WordArray#
       -> State# RealWorld
       -> State# RealWorld
    {-# INLINE bignat_or #-}
    bignat_or :: MutableWordArray# RealWorld
    -> WordArray# -> WordArray# -> State# RealWorld -> State# RealWorld
    bignat_or MutableWordArray# RealWorld
    mwa WordArray#
    wa WordArray#
    wb State# RealWorld
    s1
       | Int# -> Bool
    isTrue# (Int#
    szA Int# -> Int# -> Int#
    >=# Int#
    szB) = WordArray#
    -> Int#
    -> WordArray#
    -> Int#
    -> State# RealWorld
    -> State# RealWorld
    go WordArray#
    wa Int#
    szA WordArray#
    wb Int#
    szB State# RealWorld
    s1
       | Bool
    True                  = WordArray#
    -> Int#
    -> WordArray#
    -> Int#
    -> State# RealWorld
    -> State# RealWorld
    go WordArray#
    wb Int#
    szB WordArray#
    wa Int#
    szA State# RealWorld
    s1
       where
          !szA :: Int#
    szA = WordArray# -> Int#
    wordArraySize# WordArray#
    wa
          !szB :: Int#
    szB = WordArray# -> Int#
    wordArraySize# WordArray#
    wb
          -- nx >= ny
          go :: WordArray#
    -> Int#
    -> WordArray#
    -> Int#
    -> State# RealWorld
    -> State# RealWorld
    go WordArray#
    wx Int#
    nx WordArray#
    wy Int#
    ny State# RealWorld
    s = case IO () -> State# RealWorld -> State# RealWorld
    forall a. IO a -> State# RealWorld -> State# RealWorld
    ioVoid (MutableWordArray# RealWorld
    -> WordArray# -> WordArray# -> Int# -> IO ()
    forall s.
    MutableByteArray# s -> WordArray# -> WordArray# -> Int# -> IO ()
    c_mpn_ior_n MutableWordArray# RealWorld
    mwa WordArray#
    wx WordArray#
    wy Int#
    ny) State# RealWorld
    s of
             State# RealWorld
    s' -> MutableWordArray# RealWorld
    -> Int#
    -> WordArray#
    -> Int#
    -> Int#
    -> State# RealWorld
    -> State# RealWorld
    forall s.
    MutableByteArray# s
    -> Int# -> WordArray# -> Int# -> Int# -> State# s -> State# s
    mwaArrayCopy# MutableWordArray# RealWorld
    mwa Int#
    ny WordArray#
    wx Int#
    ny (Int#
    nx Int# -> Int# -> Int#
    -# Int#
    ny) State# RealWorld
    s'

    bignat_xor
       :: MutableWordArray# RealWorld
       -> WordArray#
       -> WordArray#
       -> State# RealWorld
       -> State# RealWorld
    {-# INLINE bignat_xor #-}
    bignat_xor :: MutableWordArray# RealWorld
    -> WordArray# -> WordArray# -> State# RealWorld -> State# RealWorld
    bignat_xor MutableWordArray# RealWorld
    mwa WordArray#
    wa WordArray#
    wb State# RealWorld
    s1
       | Int# -> Bool
    isTrue# (Int#
    szA Int# -> Int# -> Int#
    >=# Int#
    szB) = WordArray#
    -> Int#
    -> WordArray#
    -> Int#
    -> State# RealWorld
    -> State# RealWorld
    go WordArray#
    wa Int#
    szA WordArray#
    wb Int#
    szB State# RealWorld
    s1
       | Bool
    True                  = WordArray#
    -> Int#
    -> WordArray#
    -> Int#
    -> State# RealWorld
    -> State# RealWorld
    go WordArray#
    wb Int#
    szB WordArray#
    wa Int#
    szA State# RealWorld
    s1
       where
          !szA :: Int#
    szA = WordArray# -> Int#
    wordArraySize# WordArray#
    wa
          !szB :: Int#
    szB = WordArray# -> Int#
    wordArraySize# WordArray#
    wb
          -- nx >= ny
          go :: WordArray#
    -> Int#
    -> WordArray#
    -> Int#
    -> State# RealWorld
    -> State# RealWorld
    go WordArray#
    wx Int#
    nx WordArray#
    wy Int#
    ny State# RealWorld
    s = case IO () -> State# RealWorld -> State# RealWorld
    forall a. IO a -> State# RealWorld -> State# RealWorld
    ioVoid (MutableWordArray# RealWorld
    -> WordArray# -> WordArray# -> Int# -> IO ()
    forall s.
    MutableByteArray# s -> WordArray# -> WordArray# -> Int# -> IO ()
    c_mpn_xor_n MutableWordArray# RealWorld
    mwa WordArray#
    wx WordArray#
    wy Int#
    ny) State# RealWorld
    s of
             State# RealWorld
    s' -> MutableWordArray# RealWorld
    -> Int#
    -> WordArray#
    -> Int#
    -> Int#
    -> State# RealWorld
    -> State# RealWorld
    forall s.
    MutableByteArray# s
    -> Int# -> WordArray# -> Int# -> Int# -> State# s -> State# s
    mwaArrayCopy# MutableWordArray# RealWorld
    mwa Int#
    ny WordArray#
    wx Int#
    ny (Int#
    nx Int# -> Int# -> Int#
    -# Int#
    ny) State# RealWorld
    s'

    bignat_and
       :: MutableWordArray# RealWorld -- ^ Result
       -> WordArray#
       -> WordArray#
       -> State# RealWorld
       -> State# RealWorld
    {-# INLINE bignat_and #-}
    bignat_and :: MutableWordArray# RealWorld
    -> WordArray# -> WordArray# -> State# RealWorld -> State# RealWorld
    bignat_and MutableWordArray# RealWorld
    mwa WordArray#
    wa WordArray#
    wb State# RealWorld
    s = IO () -> State# RealWorld -> State# RealWorld
    forall a. IO a -> State# RealWorld -> State# RealWorld
    ioVoid (MutableWordArray# RealWorld
    -> WordArray# -> WordArray# -> Int# -> IO ()
    forall s.
    MutableByteArray# s -> WordArray# -> WordArray# -> Int# -> IO ()
    c_mpn_and_n MutableWordArray# RealWorld
    mwa WordArray#
    wa WordArray#
    wb Int#
    sz) State# RealWorld
    s
       where
          !szA :: Int#
    szA = WordArray# -> Int#
    wordArraySize# WordArray#
    wa
          !szB :: Int#
    szB = WordArray# -> Int#
    wordArraySize# WordArray#
    wb
          !sz :: Int#
    sz  = Int# -> Int# -> Int#
    minI# Int#
    szA Int#
    szB

    bignat_and_not
       :: MutableWordArray# RealWorld -- ^ Result
       -> WordArray#
       -> WordArray#
       -> State# RealWorld
       -> State# RealWorld
    {-# INLINE bignat_and_not #-}
    bignat_and_not :: MutableWordArray# RealWorld
    -> WordArray# -> WordArray# -> State# RealWorld -> State# RealWorld
    bignat_and_not MutableWordArray# RealWorld
    mwa WordArray#
    wa WordArray#
    wb State# RealWorld
    s =
       case IO () -> State# RealWorld -> State# RealWorld
    forall a. IO a -> State# RealWorld -> State# RealWorld
    ioVoid (MutableWordArray# RealWorld
    -> WordArray# -> WordArray# -> Int# -> IO ()
    forall s.
    MutableByteArray# s -> WordArray# -> WordArray# -> Int# -> IO ()
    c_mpn_andn_n MutableWordArray# RealWorld
    mwa WordArray#
    wa WordArray#
    wb Int#
    n) State# RealWorld
    s of
          State# RealWorld
    s' -> MutableWordArray# RealWorld
    -> Int#
    -> WordArray#
    -> Int#
    -> Int#
    -> State# RealWorld
    -> State# RealWorld
    forall s.
    MutableByteArray# s
    -> Int# -> WordArray# -> Int# -> Int# -> State# s -> State# s
    mwaArrayCopy# MutableWordArray# RealWorld
    mwa Int#
    szB WordArray#
    wa Int#
    szB (Int#
    szA Int# -> Int# -> Int#
    -# Int#
    szB) State# RealWorld
    s'
       where
          !szA :: Int#
    szA = WordArray# -> Int#
    wordArraySize# WordArray#
    wa
          !szB :: Int#
    szB = WordArray# -> Int#
    wordArraySize# WordArray#
    wb
          !n :: Int#
    n   = Int# -> Int# -> Int#
    minI# Int#
    szA Int#
    szB

    bignat_quotrem
       :: MutableWordArray# RealWorld
       -> MutableWordArray# RealWorld
       -> WordArray#
       -> WordArray#
       -> State# RealWorld
       -> State# RealWorld
    bignat_quotrem :: MutableWordArray# RealWorld
    -> MutableWordArray# RealWorld
    -> WordArray#
    -> WordArray#
    -> State# RealWorld
    -> State# RealWorld
    bignat_quotrem MutableWordArray# RealWorld
    mwq MutableWordArray# RealWorld
    mwr WordArray#
    wa WordArray#
    wb State# RealWorld
    s =
       IO () -> State# RealWorld -> State# RealWorld
    forall a. IO a -> State# RealWorld -> State# RealWorld
    ioVoid (MutableWordArray# RealWorld
    -> MutableWordArray# RealWorld
    -> Int#
    -> WordArray#
    -> Int#
    -> WordArray#
    -> Int#
    -> IO ()
    forall s.
    MutableByteArray# s
    -> MutableByteArray# s
    -> Int#
    -> WordArray#
    -> Int#
    -> WordArray#
    -> Int#
    -> IO ()
    c_mpn_tdiv_qr MutableWordArray# RealWorld
    mwq MutableWordArray# RealWorld
    mwr Int#
    0# WordArray#
    wa Int#
    szA WordArray#
    wb Int#
    szB) State# RealWorld
    s
       where
          szA :: Int#
    szA = WordArray# -> Int#
    wordArraySize# WordArray#
    wa
          szB :: Int#
    szB = WordArray# -> Int#
    wordArraySize# WordArray#
    wb

    bignat_quot
       :: MutableWordArray# RealWorld
       -> WordArray#
       -> WordArray#
       -> State# RealWorld
       -> State# RealWorld
    bignat_quot :: MutableWordArray# RealWorld
    -> WordArray# -> WordArray# -> State# RealWorld -> State# RealWorld
    bignat_quot MutableWordArray# RealWorld
    mwq WordArray#
    wa WordArray#
    wb State# RealWorld
    s =
       IO () -> State# RealWorld -> State# RealWorld
    forall a. IO a -> State# RealWorld -> State# RealWorld
    ioVoid (MutableWordArray# RealWorld
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO ()
    forall s.
    MutableByteArray# s
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO ()
    c_mpn_tdiv_q MutableWordArray# RealWorld
    mwq WordArray#
    wa Int#
    szA WordArray#
    wb Int#
    szB) State# RealWorld
    s
       where
          szA :: Int#
    szA = WordArray# -> Int#
    wordArraySize# WordArray#
    wa
          szB :: Int#
    szB = WordArray# -> Int#
    wordArraySize# WordArray#
    wb

    bignat_rem
       :: MutableWordArray# RealWorld
       -> WordArray#
       -> WordArray#
       -> State# RealWorld
       -> State# RealWorld
    bignat_rem :: MutableWordArray# RealWorld
    -> WordArray# -> WordArray# -> State# RealWorld -> State# RealWorld
    bignat_rem MutableWordArray# RealWorld
    mwr WordArray#
    wa WordArray#
    wb State# RealWorld
    s =
       IO () -> State# RealWorld -> State# RealWorld
    forall a. IO a -> State# RealWorld -> State# RealWorld
    ioVoid (MutableWordArray# RealWorld
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO ()
    forall s.
    MutableByteArray# s
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO ()
    c_mpn_tdiv_r MutableWordArray# RealWorld
    mwr WordArray#
    wa Int#
    szA WordArray#
    wb Int#
    szB) State# RealWorld
    s
       where
          szA :: Int#
    szA = WordArray# -> Int#
    wordArraySize# WordArray#
    wa
          szB :: Int#
    szB = WordArray# -> Int#
    wordArraySize# WordArray#
    wb

    bignat_quotrem_word
       :: MutableWordArray# RealWorld -- ^ Quotient
       -> WordArray#
       -> Word#
       -> State# RealWorld
       -> (# State# RealWorld, Word# #)
    bignat_quotrem_word :: MutableWordArray# RealWorld
    -> WordArray#
    -> Word#
    -> State# RealWorld
    -> (# State# RealWorld, Word# #)
    bignat_quotrem_word MutableWordArray# RealWorld
    mwq WordArray#
    wa Word#
    b State# RealWorld
    s =
       IO Word -> State# RealWorld -> (# State# RealWorld, Word# #)
    ioWord# (MutableWordArray# RealWorld
    -> Int# -> WordArray# -> Int# -> Word# -> IO Word
    forall s.
    MutableByteArray# s
    -> Int# -> WordArray# -> Int# -> Word# -> IO Word
    c_mpn_divrem_1 MutableWordArray# RealWorld
    mwq Int#
    0# WordArray#
    wa Int#
    szA Word#
    b) State# RealWorld
    s
       where
          szA :: Int#
    szA = WordArray# -> Int#
    wordArraySize# WordArray#
    wa

    bignat_quot_word
       :: MutableWordArray# RealWorld -- ^ Quotient
       -> WordArray#
       -> Word#
       -> State# RealWorld
       -> State# RealWorld
    bignat_quot_word :: MutableWordArray# RealWorld
    -> WordArray# -> Word# -> State# RealWorld -> State# RealWorld
    bignat_quot_word MutableWordArray# RealWorld
    mwq WordArray#
    wa Word#
    b State# RealWorld
    s =
       case MutableWordArray# RealWorld
    -> WordArray#
    -> Word#
    -> State# RealWorld
    -> (# State# RealWorld, Word# #)
    bignat_quotrem_word MutableWordArray# RealWorld
    mwq WordArray#
    wa Word#
    b State# RealWorld
    s of
          (# State# RealWorld
    s', Word#
    _ #) -> State# RealWorld
    s'

    bignat_rem_word
       :: WordArray#
       -> Word#
       -> Word#
    bignat_rem_word :: WordArray# -> Word# -> Word#
    bignat_rem_word WordArray#
    wa Word#
    b =
       WordArray# -> Int# -> Word# -> Word#
    c_mpn_mod_1 WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) Word#
    b

    bignat_gcd
       :: MutableWordArray# RealWorld
       -> WordArray#
       -> WordArray#
       -> State# RealWorld
       -> State# RealWorld
    bignat_gcd :: MutableWordArray# RealWorld
    -> WordArray# -> WordArray# -> State# RealWorld -> State# RealWorld
    bignat_gcd MutableWordArray# RealWorld
    mwr WordArray#
    wa WordArray#
    wb State# RealWorld
    s =
       -- wa > wb
       case IO Int -> State# RealWorld -> (# State# RealWorld, Int# #)
    ioInt# (MutableWordArray# RealWorld
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO Int
    forall s.
    MutableByteArray# s
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO Int
    c_mpn_gcd# MutableWordArray# RealWorld
    mwr WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) WordArray#
    wb (WordArray# -> Int#
    wordArraySize# WordArray#
    wb)) State# RealWorld
    s of
          (# State# RealWorld
    s', Int#
    sz #) -> MutableWordArray# RealWorld
    -> Int# -> State# RealWorld -> State# RealWorld
    forall s. MutableByteArray# s -> Int# -> State# s -> State# s
    mwaSetSize# MutableWordArray# RealWorld
    mwr (Int# -> Int#
    narrowGmpSize# Int#
    sz) State# RealWorld
    s'

    bignat_gcd_word
       :: WordArray#
       -> Word#
       -> Word#
    bignat_gcd_word :: WordArray# -> Word# -> Word#
    bignat_gcd_word WordArray#
    wa Word#
    b = WordArray# -> Int# -> Word# -> Word#
    c_mpn_gcd_1# WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) Word#
    b

    bignat_gcd_word_word
       :: Word#
       -> Word#
       -> Word#
    bignat_gcd_word_word :: Word# -> Word# -> Word#
    bignat_gcd_word_word = Word# -> Word# -> Word#
    integer_gmp_gcd_word

    bignat_encode_double :: WordArray# -> Int# -> Double#
    bignat_encode_double :: WordArray# -> Int# -> Double#
    bignat_encode_double WordArray#
    wa Int#
    e = WordArray# -> Int# -> Int# -> Double#
    c_mpn_get_d WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) Int#
    e

    bignat_shiftr_neg
       :: MutableWordArray# RealWorld
       -> WordArray#
       -> Word#
       -> State# RealWorld
       -> State# RealWorld
    bignat_shiftr_neg :: MutableWordArray# RealWorld
    -> WordArray# -> Word# -> State# RealWorld -> State# RealWorld
    bignat_shiftr_neg MutableWordArray# RealWorld
    mwa WordArray#
    wa Word#
    n State# RealWorld
    s =
       IO Word -> State# RealWorld -> State# RealWorld
    forall a. IO a -> State# RealWorld -> State# RealWorld
    ioVoid (MutableWordArray# RealWorld
    -> WordArray# -> Int# -> Word# -> IO Word
    forall s.
    MutableByteArray# s -> WordArray# -> Int# -> Word# -> IO Word
    c_mpn_rshift_2c MutableWordArray# RealWorld
    mwa WordArray#
    wa (WordArray# -> Int#
    wordArraySize# WordArray#
    wa) Word#
    n) State# RealWorld
    s

    bignat_powmod_word
       :: WordArray#
       -> WordArray#
       -> Word#
       -> Word#
    bignat_powmod_word :: WordArray# -> WordArray# -> Word# -> Word#
    bignat_powmod_word WordArray#
    b WordArray#
    e Word#
    m =
       WordArray# -> Int# -> WordArray# -> Int# -> Word# -> Word#
    integer_gmp_powm1# WordArray#
    b (WordArray# -> Int#
    wordArraySize# WordArray#
    b) WordArray#
    e (WordArray# -> Int#
    wordArraySize# WordArray#
    e) Word#
    m

    bignat_powmod_words
       :: Word#
       -> Word#
       -> Word#
       -> Word#
    bignat_powmod_words :: Word# -> Word# -> Word# -> Word#
    bignat_powmod_words = Word# -> Word# -> Word# -> Word#
    integer_gmp_powm_word

    bignat_powmod
       :: MutableWordArray# RealWorld
       -> WordArray#
       -> WordArray#
       -> WordArray#
       -> State# RealWorld
       -> State# RealWorld
    bignat_powmod :: MutableWordArray# RealWorld
    -> WordArray#
    -> WordArray#
    -> WordArray#
    -> State# RealWorld
    -> State# RealWorld
    bignat_powmod MutableWordArray# RealWorld
    r WordArray#
    b WordArray#
    e WordArray#
    m State# RealWorld
    s = MutableWordArray# RealWorld
    -> Int#
    -> WordArray#
    -> WordArray#
    -> WordArray#
    -> State# RealWorld
    -> State# RealWorld
    sbignat_powmod MutableWordArray# RealWorld
    r (WordArray# -> Int#
    wordArraySize# WordArray#
    b) WordArray#
    b WordArray#
    e WordArray#
    m State# RealWorld
    s

    integer_powmod
       :: Integer
       -> Natural
       -> Natural
       -> Natural
    integer_powmod :: Integer -> Natural -> Natural -> Natural
    integer_powmod Integer
    b Natural
    e Natural
    m = WordArray# -> Natural
    naturalFromBigNat# (Int#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> WordArray#
    withNewWordArray# Int#
    szm MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld
    io)
       where
          !be :: WordArray#
    be = Natural -> WordArray#
    naturalToBigNat# Natural
    e
          !bm :: WordArray#
    bm = Natural -> WordArray#
    naturalToBigNat# Natural
    m
          !(# Int#
    sb, WordArray#
    bb #) = Integer -> (# Int#, WordArray# #)
    integerToBigNatSign# Integer
    b
          !szb :: Int#
    szb = WordArray# -> Int#
    bigNatSize# WordArray#
    bb
          !szm :: Int#
    szm = WordArray# -> Int#
    bigNatSize# WordArray#
    bm
          !ssb :: Int#
    ssb = case Int#
    sb of -- signed size of b
                   Int#
    0# -> Int#
    szb
                   Int#
    _  -> Int# -> Int#
    negateInt# Int#
    szb

          io :: MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld
    io MutableWordArray# RealWorld
    r State# RealWorld
    s = MutableWordArray# RealWorld
    -> Int#
    -> WordArray#
    -> WordArray#
    -> WordArray#
    -> State# RealWorld
    -> State# RealWorld
    sbignat_powmod MutableWordArray# RealWorld
    r Int#
    ssb WordArray#
    bb WordArray#
    be WordArray#
    bm State# RealWorld
    s

    sbignat_powmod
       :: MutableWordArray# RealWorld
       -> Int#
       -> WordArray#
       -> WordArray#
       -> WordArray#
       -> State# RealWorld
       -> State# RealWorld
    sbignat_powmod :: MutableWordArray# RealWorld
    -> Int#
    -> WordArray#
    -> WordArray#
    -> WordArray#
    -> State# RealWorld
    -> State# RealWorld
    sbignat_powmod MutableWordArray# RealWorld
    r Int#
    b_signed_size WordArray#
    b WordArray#
    e WordArray#
    m State# RealWorld
    s =
       case IO Int -> State# RealWorld -> (# State# RealWorld, Int# #)
    ioInt# (MutableWordArray# RealWorld
    -> WordArray#
    -> Int#
    -> WordArray#
    -> Int#
    -> WordArray#
    -> Int#
    -> IO Int
    integer_gmp_powm# MutableWordArray# RealWorld
    r WordArray#
    b Int#
    b_signed_size WordArray#
    e (WordArray# -> Int#
    wordArraySize# WordArray#
    e) WordArray#
    m (WordArray# -> Int#
    wordArraySize# WordArray#
    m)) State# RealWorld
    s of
          (# State# RealWorld
    s', Int#
    n #) -> MutableWordArray# RealWorld
    -> Int# -> State# RealWorld -> State# RealWorld
    forall s. MutableByteArray# s -> Int# -> State# s -> State# s
    mwaSetSize# MutableWordArray# RealWorld
    r (Int# -> Int#
    narrowGmpSize# Int#
    n) State# RealWorld
    s'

    integer_gcde
       :: Integer
       -> Integer
       -> (# Integer, Integer, Integer #)
    integer_gcde :: Integer -> Integer -> (# Integer, Integer, Integer #)
    integer_gcde Integer
    a Integer
    b = case (State# RealWorld
     -> (# State# RealWorld, (# Integer, Integer, Integer #) #))
    -> (# State# RealWorld, (# Integer, Integer, Integer #) #)
    forall o. (State# RealWorld -> o) -> o
    runRW# State# RealWorld
    -> (# State# RealWorld, (# Integer, Integer, Integer #) #)
    io of (# State# RealWorld
    _, (# Integer, Integer, Integer #)
    a #) -> (# Integer, Integer, Integer #)
    a
       where
          !(# Int#
    sa, WordArray#
    ba #) = Integer -> (# Int#, WordArray# #)
    integerToBigNatSign# Integer
    a
          !(# Int#
    sb, WordArray#
    bb #) = Integer -> (# Int#, WordArray# #)
    integerToBigNatSign# Integer
    b
          !sza :: Int#
    sza          = WordArray# -> Int#
    bigNatSize# WordArray#
    ba
          !szb :: Int#
    szb          = WordArray# -> Int#
    bigNatSize# WordArray#
    bb
          -- signed sizes of a and b
          !ssa :: Int#
    ssa          = case Int#
    sa of
                               Int#
    0# -> Int#
    sza
                               Int#
    _  -> Int# -> Int#
    negateInt# Int#
    sza
          !ssb :: Int#
    ssb          = case Int#
    sb of
                            Int#
    0# -> Int#
    szb
                            Int#
    _  -> Int# -> Int#
    negateInt# Int#
    szb

          -- gcd(a,b) < min(a,b)
          !g_init_sz :: Int#
    g_init_sz = Int# -> Int# -> Int#
    minI# Int#
    sza Int#
    szb

          -- According to https://gmplib.org/manual/Number-Theoretic-Functions.html#index-mpz_005fgcdext
          -- a*x + b*y = g
          -- abs(x) < abs(b) / (2 g) < abs(b)
          -- abs(y) < abs(a) / (2 g) < abs(a)
          !x_init_sz :: Int#
    x_init_sz = Int#
    szb
          !y_init_sz :: Int#
    y_init_sz = Int#
    sza

          io :: State# RealWorld
    -> (# State# RealWorld, (# Integer, Integer, Integer #) #)
    io State# RealWorld
    s =
             -- allocate output arrays
             case Int#
    -> State# RealWorld
    -> (# State# RealWorld, MutableWordArray# RealWorld #)
    forall s. Int# -> State# s -> (# State# s, MutableWordArray# s #)
    newWordArray# Int#
    g_init_sz State# RealWorld
    s     of { (# State# RealWorld
    s, MutableWordArray# RealWorld
    mbg #) ->
             case Int#
    -> State# RealWorld
    -> (# State# RealWorld, MutableWordArray# RealWorld #)
    forall s. Int# -> State# s -> (# State# s, MutableWordArray# s #)
    newWordArray# Int#
    x_init_sz State# RealWorld
    s     of { (# State# RealWorld
    s, MutableWordArray# RealWorld
    mbx #) ->
             case Int#
    -> State# RealWorld
    -> (# State# RealWorld, MutableWordArray# RealWorld #)
    forall s. Int# -> State# s -> (# State# s, MutableWordArray# s #)
    newWordArray# Int#
    y_init_sz State# RealWorld
    s     of { (# State# RealWorld
    s, MutableWordArray# RealWorld
    mby #) ->
             -- allocate space to return sizes (3x4 = 12)
             case Int#
    -> State# RealWorld
    -> (# State# RealWorld, MutableWordArray# RealWorld #)
    forall s. Int# -> State# s -> (# State# s, MutableWordArray# s #)
    newPinnedByteArray# Int#
    12# State# RealWorld
    s     of { (# State# RealWorld
    s, MutableWordArray# RealWorld
    mszs #) ->
             case MutableWordArray# RealWorld
    -> State# RealWorld -> (# State# RealWorld, WordArray# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, WordArray# #)
    unsafeFreezeByteArray# MutableWordArray# RealWorld
    mszs State# RealWorld
    s of { (# State# RealWorld
    s, WordArray#
    szs #) ->
             let !ssx_ptr :: Addr#
    ssx_ptr = WordArray# -> Addr#
    byteArrayContents# WordArray#
    szs in
             let !ssy_ptr :: Addr#
    ssy_ptr = Addr#
    ssx_ptr Addr# -> Int# -> Addr#
    `plusAddr#` Int#
    4# in
             let !sg_ptr :: Addr#
    sg_ptr  = Addr#
    ssy_ptr Addr# -> Int# -> Addr#
    `plusAddr#` Int#
    4# in
             -- call GMP
             case IO () -> State# RealWorld -> State# RealWorld
    forall a. IO a -> State# RealWorld -> State# RealWorld
    ioVoid (MutableWordArray# RealWorld
    -> Addr#
    -> MutableWordArray# RealWorld
    -> Addr#
    -> MutableWordArray# RealWorld
    -> Addr#
    -> WordArray#
    -> Int#
    -> WordArray#
    -> Int#
    -> IO ()
    forall s.
    MutableByteArray# s
    -> Addr#
    -> MutableByteArray# s
    -> Addr#
    -> MutableByteArray# s
    -> Addr#
    -> WordArray#
    -> Int#
    -> WordArray#
    -> Int#
    -> IO ()
    integer_gmp_gcdext# MutableWordArray# RealWorld
    mbx Addr#
    ssx_ptr MutableWordArray# RealWorld
    mby Addr#
    ssy_ptr MutableWordArray# RealWorld
    mbg Addr#
    sg_ptr WordArray#
    ba Int#
    ssa WordArray#
    bb Int#
    ssb) State# RealWorld
    s of { State# RealWorld
    s ->
             -- read sizes
             case Addr# -> Int# -> State# RealWorld -> (# State# RealWorld, Int32# #)
    forall d. Addr# -> Int# -> State# d -> (# State# d, Int32# #)
    readInt32OffAddr# Addr#
    ssx_ptr Int#
    0# State# RealWorld
    s of { (# State# RealWorld
    s, Int32#
    ssx #) ->
             case Addr# -> Int# -> State# RealWorld -> (# State# RealWorld, Int32# #)
    forall d. Addr# -> Int# -> State# d -> (# State# d, Int32# #)
    readInt32OffAddr# Addr#
    ssy_ptr Int#
    0# State# RealWorld
    s of { (# State# RealWorld
    s, Int32#
    ssy #) ->
             case Addr# -> Int# -> State# RealWorld -> (# State# RealWorld, Int32# #)
    forall d. Addr# -> Int# -> State# d -> (# State# d, Int32# #)
    readInt32OffAddr# Addr#
    sg_ptr  Int#
    0# State# RealWorld
    s of { (# State# RealWorld
    s, Int32#
    sg #) ->
             case WordArray# -> State# RealWorld -> State# RealWorld
    forall a d. a -> State# d -> State# d
    touch# WordArray#
    szs State# RealWorld
    s of { State# RealWorld
    s ->
             -- shrink x, y and g to their actual sizes and freeze them
             let !sx :: Int#
    sx = Int# -> Int#
    absI# (Int32# -> Int#
    int32ToInt# Int32#
    ssx) in
             let !sy :: Int#
    sy = Int# -> Int#
    absI# (Int32# -> Int#
    int32ToInt# Int32#
    ssy) in
             case MutableWordArray# RealWorld
    -> Int# -> State# RealWorld -> State# RealWorld
    forall s. MutableByteArray# s -> Int# -> State# s -> State# s
    mwaSetSize# MutableWordArray# RealWorld
    mbx Int#
    sx State# RealWorld
    s of { State# RealWorld
    s ->
             case MutableWordArray# RealWorld
    -> Int# -> State# RealWorld -> State# RealWorld
    forall s. MutableByteArray# s -> Int# -> State# s -> State# s
    mwaSetSize# MutableWordArray# RealWorld
    mby Int#
    sy State# RealWorld
    s of { State# RealWorld
    s ->
             case MutableWordArray# RealWorld
    -> Int# -> State# RealWorld -> State# RealWorld
    forall s. MutableByteArray# s -> Int# -> State# s -> State# s
    mwaSetSize# MutableWordArray# RealWorld
    mbg (Int32# -> Int#
    int32ToInt# Int32#
    sg) State# RealWorld
    s of { State# RealWorld
    s ->

             -- return x, y and g as Integer
             case MutableWordArray# RealWorld
    -> State# RealWorld -> (# State# RealWorld, WordArray# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, WordArray# #)
    unsafeFreezeByteArray# MutableWordArray# RealWorld
    mbx State# RealWorld
    s of { (# State# RealWorld
    s, WordArray#
    bx #) ->
             case MutableWordArray# RealWorld
    -> State# RealWorld -> (# State# RealWorld, WordArray# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, WordArray# #)
    unsafeFreezeByteArray# MutableWordArray# RealWorld
    mby State# RealWorld
    s of { (# State# RealWorld
    s, WordArray#
    by #) ->
             case MutableWordArray# RealWorld
    -> State# RealWorld -> (# State# RealWorld, WordArray# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, WordArray# #)
    unsafeFreezeByteArray# MutableWordArray# RealWorld
    mbg State# RealWorld
    s of { (# State# RealWorld
    s, WordArray#
    bg #) ->

             (# State# RealWorld
    s, (# WordArray# -> Integer
    integerFromBigNat# WordArray#
    bg
                   ,  Int# -> WordArray# -> Integer
    integerFromBigNatSign# (Int32# -> Int#
    int32ToInt# Int32#
    ssx Int# -> Int# -> Int#
    <# Int#
    0#) WordArray#
    bx
                   ,  Int# -> WordArray# -> Integer
    integerFromBigNatSign# (Int32# -> Int#
    int32ToInt# Int32#
    ssy Int# -> Int# -> Int#
    <# Int#
    0#) WordArray#
    by #) #)
             }}}}}}}}}}}}}}}}

    integer_recip_mod
       :: Integer
       -> Natural
       -> (# Natural | () #)
    integer_recip_mod :: Integer -> Natural -> (# Natural | () #)
    integer_recip_mod Integer
    x Natural
    m =
       let
          !(#  Int#
    sign_x, WordArray#
    bx #) = Integer -> (# Int#, WordArray# #)
    integerToBigNatSign# Integer
    x
          !bm :: WordArray#
    bm = Natural -> WordArray#
    naturalToBigNat# Natural
    m
          !br :: WordArray#
    br = Int# -> WordArray# -> WordArray# -> WordArray#
    sbignat_recip_mod Int#
    sign_x WordArray#
    bx WordArray#
    bm
       in if Int# -> Bool
    isTrue# (WordArray# -> Int#
    bigNatIsZero# WordArray#
    br)
             then (# | () #)
             else (# WordArray# -> Natural
    naturalFromBigNat# WordArray#
    br | #)

    -- | Return 0 for invalid inputs
    sbignat_recip_mod :: Int# -> BigNat# -> BigNat# -> BigNat#
    sbignat_recip_mod :: Int# -> WordArray# -> WordArray# -> WordArray#
    sbignat_recip_mod Int#
    sign_x WordArray#
    x WordArray#
    m = Int#
    -> (MutableWordArray# RealWorld
        -> State# RealWorld -> State# RealWorld)
    -> WordArray#
    withNewWordArray# Int#
    szm MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld
    io
      where
        io :: MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld
    io MutableWordArray# RealWorld
    r State# RealWorld
    s = case IO Int -> State# RealWorld -> (# State# RealWorld, Int# #)
    ioInt# (MutableWordArray# RealWorld
    -> WordArray# -> Int# -> WordArray# -> Int# -> IO Int
    integer_gmp_invert# MutableWordArray# RealWorld
    r WordArray#
    x Int#
    ssx WordArray#
    m Int#
    szm) State# RealWorld
    s of
                   (# State# RealWorld
    s, Int#
    rn #) -> MutableWordArray# RealWorld
    -> Int# -> State# RealWorld -> State# RealWorld
    forall s. MutableByteArray# s -> Int# -> State# s -> State# s
    mwaSetSize# MutableWordArray# RealWorld
    r (Int# -> Int#
    narrowGmpSize# Int#
    rn) State# RealWorld
    s
        !szx :: Int#
    szx  = WordArray# -> Int#
    bigNatSize# WordArray#
    x
        !szm :: Int#
    szm  = WordArray# -> Int#
    bigNatSize# WordArray#
    m
        !ssx :: Int#
    ssx = case Int#
    sign_x of -- signed size of x
                Int#
    0# -> Int#
    szx
                Int#
    _  -> Int# -> Int#
    negateInt# Int#
    szx

    ----------------------------------------------------------------------
    -- FFI ccall imports

    foreign import ccall unsafe "integer_gmp_gcd_word"
      integer_gmp_gcd_word :: GmpLimb# -> GmpLimb# -> GmpLimb#

    foreign import ccall unsafe "integer_gmp_mpn_gcd_1"
      c_mpn_gcd_1# :: ByteArray# -> GmpSize# -> GmpLimb# -> GmpLimb#

    foreign import ccall unsafe "integer_gmp_mpn_gcd"
      c_mpn_gcd# :: MutableByteArray# s -> ByteArray# -> GmpSize#
                    -> ByteArray# -> GmpSize# -> IO GmpSize

    foreign import ccall unsafe "integer_gmp_gcdext" integer_gmp_gcdext#
      :: MutableByteArray# s -> Addr#
      -> MutableByteArray# s -> Addr#
      -> MutableByteArray# s -> Addr#
      -> ByteArray# -> GmpSize#
      -> ByteArray# -> GmpSize#
      -> IO ()

    foreign import ccall unsafe "integer_gmp_invert"
      integer_gmp_invert# :: MutableByteArray# RealWorld
                             -> ByteArray# -> GmpSize#
                             -> ByteArray# -> GmpSize# -> IO GmpSize

    -- mp_limb_t mpn_add_1 (mp_limb_t *rp, const mp_limb_t *s1p, mp_size_t n,
    --                      mp_limb_t s2limb)
    foreign import ccall unsafe "gmp.h __gmpn_add_1"
      c_mpn_add_1 :: MutableByteArray# s -> ByteArray# -> GmpSize# -> GmpLimb#
                     -> IO GmpLimb

    -- mp_limb_t mpn_sub_1 (mp_limb_t *rp, const mp_limb_t *s1p, mp_size_t n,
    --                      mp_limb_t s2limb)
    foreign import ccall unsafe "gmp.h __gmpn_sub_1"
      c_mpn_sub_1 :: MutableByteArray# s -> ByteArray# -> GmpSize# -> GmpLimb#
                     -> IO GmpLimb

    -- mp_limb_t mpn_mul_1 (mp_limb_t *rp, const mp_limb_t *s1p, mp_size_t n,
    --                      mp_limb_t s2limb)
    foreign import ccall unsafe "gmp.h __gmpn_mul_1"
      c_mpn_mul_1 :: MutableByteArray# s -> ByteArray# -> GmpSize# -> GmpLimb#
                     -> IO GmpLimb

    -- mp_limb_t mpn_add (mp_limb_t *rp, const mp_limb_t *s1p, mp_size_t s1n,
    --                    const mp_limb_t *s2p, mp_size_t s2n)
    foreign import ccall unsafe "gmp.h __gmpn_add"
      c_mpn_add :: MutableByteArray# s -> ByteArray# -> GmpSize#
                   -> ByteArray# -> GmpSize# -> IO GmpLimb

    -- mp_limb_t mpn_sub (mp_limb_t *rp, const mp_limb_t *s1p, mp_size_t s1n,
    --                    const mp_limb_t *s2p, mp_size_t s2n)
    foreign import ccall unsafe "gmp.h __gmpn_sub"
      c_mpn_sub :: MutableByteArray# s -> ByteArray# -> GmpSize# -> ByteArray#
                   -> GmpSize# -> IO GmpLimb

    -- mp_limb_t mpn_mul (mp_limb_t *rp, const mp_limb_t *s1p, mp_size_t s1n,
    --                    const mp_limb_t *s2p, mp_size_t s2n)
    foreign import ccall unsafe "gmp.h __gmpn_mul"
      c_mpn_mul :: MutableByteArray# s -> ByteArray# -> GmpSize# -> ByteArray#
                   -> GmpSize# -> IO GmpLimb

    -- int mpn_cmp (const mp_limb_t *s1p, const mp_limb_t *s2p, mp_size_t n)
    foreign import ccall unsafe "gmp.h __gmpn_cmp"
      c_mpn_cmp :: ByteArray# -> ByteArray# -> GmpSize# -> Int#

    -- void mpn_tdiv_qr (mp_limb_t *qp, mp_limb_t *rp, mp_size_t qxn,
    --                   const mp_limb_t *np, mp_size_t nn,
    --                   const mp_limb_t *dp, mp_size_t dn)
    foreign import ccall unsafe "gmp.h __gmpn_tdiv_qr"
      c_mpn_tdiv_qr :: MutableByteArray# s -> MutableByteArray# s -> GmpSize#
                       -> ByteArray# -> GmpSize# -> ByteArray# -> GmpSize# -> IO ()

    foreign import ccall unsafe "integer_gmp_mpn_tdiv_q"
      c_mpn_tdiv_q :: MutableByteArray# s -> ByteArray# -> GmpSize# -> ByteArray#
                      -> GmpSize# -> IO ()

    foreign import ccall unsafe "integer_gmp_mpn_tdiv_r"
      c_mpn_tdiv_r :: MutableByteArray# s -> ByteArray# -> GmpSize# -> ByteArray#
                      -> GmpSize# -> IO ()

    -- mp_limb_t mpn_divrem_1 (mp_limb_t *r1p, mp_size_t qxn, mp_limb_t *s2p,
    --                         mp_size_t s2n, mp_limb_t s3limb)
    foreign import ccall unsafe "gmp.h __gmpn_divrem_1"
      c_mpn_divrem_1 :: MutableByteArray# s -> GmpSize# -> ByteArray# -> GmpSize#
                        -> GmpLimb# -> IO GmpLimb

    -- mp_limb_t mpn_mod_1 (const mp_limb_t *s1p, mp_size_t s1n, mp_limb_t s2limb)
    foreign import ccall unsafe "gmp.h __gmpn_mod_1"
      c_mpn_mod_1 :: ByteArray# -> GmpSize# -> GmpLimb# -> GmpLimb#

    -- mp_limb_t integer_gmp_mpn_rshift (mp_limb_t rp[], const mp_limb_t sp[],
    --                                   mp_size_t sn, mp_bitcnt_t count)
    foreign import ccall unsafe "integer_gmp_mpn_rshift"
      c_mpn_rshift :: MutableByteArray# s -> ByteArray# -> GmpSize# -> Word#
                      -> IO GmpLimb

    -- mp_limb_t integer_gmp_mpn_rshift (mp_limb_t rp[], const mp_limb_t sp[],
    --                                   mp_size_t sn, mp_bitcnt_t count)
    foreign import ccall unsafe "integer_gmp_mpn_rshift_2c"
      c_mpn_rshift_2c :: MutableByteArray# s -> ByteArray# -> GmpSize# -> Word#
                         -> IO GmpLimb

    -- mp_limb_t integer_gmp_mpn_lshift (mp_limb_t rp[], const mp_limb_t sp[],
    --                                   mp_size_t sn, mp_bitcnt_t count)
    foreign import ccall unsafe "integer_gmp_mpn_lshift"
      c_mpn_lshift :: MutableByteArray# s -> ByteArray# -> GmpSize# -> Word#
                      -> IO GmpLimb

    -- void mpn_and_n (mp_limb_t *rp, const mp_limb_t *s1p, const mp_limb_t *s2p,
    --                 mp_size_t n)
    foreign import ccall unsafe "integer_gmp_mpn_and_n"
      c_mpn_and_n :: MutableByteArray# s -> ByteArray# -> ByteArray# -> GmpSize#
                     -> IO ()

    -- void mpn_andn_n (mp_limb_t *rp, const mp_limb_t *s1p, const mp_limb_t *s2p,
    --                  mp_size_t n)
    foreign import ccall unsafe "integer_gmp_mpn_andn_n"
      c_mpn_andn_n :: MutableByteArray# s -> ByteArray# -> ByteArray# -> GmpSize#
                      -> IO ()

    -- void mpn_ior_n (mp_limb_t *rp, const mp_limb_t *s1p, const mp_limb_t *s2p,
    --                 mp_size_t n)
    foreign import ccall unsafe "integer_gmp_mpn_ior_n"
      c_mpn_ior_n :: MutableByteArray# s -> ByteArray# -> ByteArray# -> GmpSize#
                     -> IO ()

    -- void mpn_xor_n (mp_limb_t *rp, const mp_limb_t *s1p, const mp_limb_t *s2p,
    --                 mp_size_t n)
    foreign import ccall unsafe "integer_gmp_mpn_xor_n"
      c_mpn_xor_n :: MutableByteArray# s -> ByteArray# -> ByteArray# -> GmpSize#
                     -> IO ()

    -- mp_bitcnt_t mpn_popcount (const mp_limb_t *s1p, mp_size_t n)
    foreign import ccall unsafe "gmp.h __gmpn_popcount"
      c_mpn_popcount :: ByteArray# -> GmpSize# -> Word#

    -- double integer_gmp_mpn_get_d (const mp_limb_t sp[], const mp_size_t sn)
    foreign import ccall unsafe "integer_gmp_mpn_get_d"
      c_mpn_get_d :: ByteArray# -> GmpSize# -> Int# -> Double#

    foreign import ccall unsafe "integer_gmp_powm"
      integer_gmp_powm# :: MutableByteArray# RealWorld
                           -> ByteArray# -> GmpSize# -> ByteArray# -> GmpSize#
                           -> ByteArray# -> GmpSize# -> IO GmpSize

    foreign import ccall unsafe "integer_gmp_powm_word"
      integer_gmp_powm_word :: GmpLimb# -> GmpLimb# -> GmpLimb# -> GmpLimb#

    foreign import ccall unsafe "integer_gmp_powm1"
      integer_gmp_powm1# :: ByteArray# -> GmpSize# -> ByteArray# -> GmpSize#
                            -> GmpLimb# -> GmpLimb#