{-# 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

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: 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, Int# #)
forall d. Addr# -> Int# -> State# d -> (# State# d, Int# #)
readInt32OffAddr# Addr#
ssx_ptr Int#
0# State# RealWorld
s of { (# State# RealWorld
s, Int#
ssx #) ->
         case Addr# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d. Addr# -> Int# -> State# d -> (# State# d, Int# #)
readInt32OffAddr# Addr#
ssy_ptr Int#
0# State# RealWorld
s of { (# State# RealWorld
s, Int#
ssy #) ->
         case Addr# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d. Addr# -> Int# -> State# d -> (# State# d, Int# #)
readInt32OffAddr# Addr#
sg_ptr  Int#
0# State# RealWorld
s of { (# State# RealWorld
s, Int#
sg #) ->
         case WordArray# -> State# RealWorld -> State# RealWorld
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# Int#
ssx in
         let !sy :: Int#
sy = Int# -> Int#
absI# Int#
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 Int#
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# (Int#
ssx Int# -> Int# -> Int#
<# Int#
0#) WordArray#
bx
               ,  Int# -> WordArray# -> Integer
integerFromBigNatSign# (Int#
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#