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

-- | 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.BigNat.GMP where

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

import GHC.Num.WordArray
import GHC.Num.Primitives
import GHC.Prim
import GHC.Types

default ()

----------------------------------------------------------------------------
-- 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
   | Int# -> Bool
isTrue# (WordArray# -> Int#
wordArraySize# WordArray#
wb Int# -> Int# -> Int#
># WordArray# -> Int#
wordArraySize# WordArray#
wa)
   = MutableWordArray# RealWorld
-> WordArray# -> WordArray# -> State# RealWorld -> State# RealWorld
bignat_add MutableWordArray# RealWorld
mwa WordArray#
wb WordArray#
wa State# RealWorld
s

   | Bool
True
   = 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_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 =
   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 (WordArray# -> Int#
wordArraySize# WordArray#
b) 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'


----------------------------------------------------------------------
-- 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 -> MutableByteArray# s
                         -> 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#