summaryrefslogtreecommitdiff
path: root/libraries/ghc-bignum/src/GHC/Num/BigNat/FFI.hs
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ghc-bignum/src/GHC/Num/BigNat/FFI.hs')
-rw-r--r--libraries/ghc-bignum/src/GHC/Num/BigNat/FFI.hs581
1 files changed, 581 insertions, 0 deletions
diff --git a/libraries/ghc-bignum/src/GHC/Num/BigNat/FFI.hs b/libraries/ghc-bignum/src/GHC/Num/BigNat/FFI.hs
new file mode 100644
index 0000000000..3ef2f7046c
--- /dev/null
+++ b/libraries/ghc-bignum/src/GHC/Num/BigNat/FFI.hs
@@ -0,0 +1,581 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE GHCForeignImportPrim #-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnliftedFFITypes #-}
+{-# LANGUAGE NegativeLiterals #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+-- | External BigNat backend that directly call FFI operations.
+--
+-- This backend can be useful for specific compilers such as GHCJS or Asterius
+-- that replace bignat foreign calls with calls to the native platform bignat
+-- library (e.g. JavaScript's BigInt). You can also link an extra object
+-- providing the implementation.
+module GHC.Num.BigNat.FFI where
+
+import GHC.Prim
+import GHC.Types
+import GHC.Num.WordArray
+import GHC.Num.Primitives
+
+default ()
+
+-- | Compare two non-zero BigNat of the same length
+--
+-- Return:
+-- < 0 ==> LT
+-- == 0 ==> EQ
+-- > 0 ==> GT
+bignat_compare
+ :: WordArray#
+ -> WordArray#
+ -> Int#
+bignat_compare = ghc_bignat_compare
+
+foreign import ccall unsafe ghc_bignat_compare
+ :: WordArray#
+ -> WordArray#
+ -> Int#
+
+-- | Add two non-zero BigNat
+--
+-- Result is to be stored in the MutableWordArray#.
+-- The latter has size: max (size a, size b) + 1
+--
+-- The potential 0 most-significant Word (i.e. the potential carry) will be
+-- removed by the caller if it is not already done by the backend.
+bignat_add
+ :: MutableWordArray# RealWorld -- ^ Result
+ -> WordArray#
+ -> WordArray#
+ -> State# RealWorld
+ -> State# RealWorld
+bignat_add mwa wa wb s
+ = ioVoid (ghc_bignat_add mwa wa wb) s
+
+foreign import ccall unsafe ghc_bignat_add
+ :: MutableWordArray# RealWorld -- ^ Result
+ -> WordArray#
+ -> WordArray#
+ -> IO ()
+
+-- | Add a non-zero BigNat and a non-zero Word#
+--
+-- Result is to be stored in the MutableWordArray#.
+-- The latter has size: size a + 1
+--
+-- The potential 0 most-significant Word (i.e. the potential carry) will be
+-- removed by the caller if it is not already done by the backend.
+bignat_add_word
+ :: MutableWordArray# RealWorld -- ^ Result
+ -> WordArray#
+ -> Word#
+ -> State# RealWorld
+ -> State# RealWorld
+bignat_add_word mwa wa b s =
+ ioVoid (ghc_bignat_add_word mwa wa b) s
+
+foreign import ccall unsafe ghc_bignat_add_word
+ :: MutableWordArray# RealWorld -- ^ Result
+ -> WordArray#
+ -> Word#
+ -> IO ()
+
+-- | Multiply a non-zero BigNat and a non-zero Word#
+--
+-- Result is to be stored in the MutableWordArray#.
+-- The latter has size: size a + 1
+--
+-- The potential 0 most-significant Word (i.e. the potential carry) will be
+-- removed by the caller if it is not already done by the backend.
+bignat_mul_word
+ :: MutableWordArray# RealWorld -- ^ Result
+ -> WordArray#
+ -> Word#
+ -> State# RealWorld
+ -> State# RealWorld
+bignat_mul_word mwa wa b s =
+ ioVoid (ghc_bignat_mul_word mwa wa b) s
+
+foreign import ccall unsafe ghc_bignat_mul_word
+ :: MutableWordArray# RealWorld -- ^ Result
+ -> WordArray#
+ -> Word#
+ -> IO ()
+
+-- | Sub two non-zero BigNat
+--
+-- Result is to be stored in the MutableWordArray#.
+-- The latter has size: size a
+--
+-- The potential 0 most-significant Words will be removed by the caller if it is
+-- not already done by the backend.
+--
+-- Return True to indicate overflow.
+bignat_sub
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> State# RealWorld
+ -> (# State# RealWorld, Bool# #)
+bignat_sub mwa wa wb s = ioBool (ghc_bignat_sub mwa wa wb) s
+
+foreign import ccall unsafe ghc_bignat_sub
+ :: MutableWordArray# RealWorld -- ^ Result
+ -> WordArray#
+ -> WordArray#
+ -> IO Bool
+
+-- | Sub a non-zero word from a non-zero BigNat
+--
+-- Result is to be stored in the MutableWordArray#.
+-- The latter has size: size a
+--
+-- The potential 0 most-significant Words will be removed by the caller if it is
+-- not already done by the backend.
+--
+-- Return True to indicate overflow.
+bignat_sub_word
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> Word#
+ -> State# RealWorld
+ -> (# State# RealWorld, Bool# #)
+bignat_sub_word mwa wa b s = ioBool (ghc_bignat_sub_word mwa wa b) s
+
+foreign import ccall unsafe ghc_bignat_sub_word
+ :: MutableWordArray# RealWorld -- ^ Result
+ -> WordArray#
+ -> Word#
+ -> IO Bool
+
+-- | Multiply two non-zero BigNat
+--
+-- Result is to be stored in the MutableWordArray#.
+-- The latter has size: size a+size b
+--
+-- The potential 0 most-significant Word (i.e. the potential carry) will be
+-- removed by the caller if it is not already done by the backend.
+bignat_mul
+ :: MutableWordArray# RealWorld -- ^ Result
+ -> WordArray#
+ -> WordArray#
+ -> State# RealWorld
+ -> State# RealWorld
+bignat_mul mwa wa wb s = ioVoid (ghc_bignat_mul mwa wa wb) s
+
+foreign import ccall unsafe ghc_bignat_mul
+ :: MutableWordArray# RealWorld -- ^ Result
+ -> WordArray#
+ -> WordArray#
+ -> IO ()
+
+-- | PopCount of a non-zero BigNat
+bignat_popcount :: WordArray# -> Word#
+bignat_popcount = ghc_bignat_popcount
+
+foreign import ccall unsafe ghc_bignat_popcount
+ :: WordArray#
+ -> Word#
+
+-- | Left-shift a non-zero BigNat by a non-zero amount of bits
+--
+-- Result is to be stored in the MutableWordArray#.
+-- The latter has size: size a + required new limbs
+--
+-- The potential 0 most-significant Word (i.e. the potential carry) will be
+-- removed by the caller if it is not already done by the backend.
+bignat_shiftl
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> Word#
+ -> State# RealWorld
+ -> State# RealWorld
+bignat_shiftl mwa wa n s = ioVoid (ghc_bignat_shiftl mwa wa n) s
+
+foreign import ccall unsafe ghc_bignat_shiftl
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> Word#
+ -> IO ()
+
+-- | Right-shift a non-zero BigNat by a non-zero amount of bits
+--
+-- Result is to be stored in the MutableWordArray#.
+-- The latter has size: required limbs
+--
+-- The potential 0 most-significant Word (i.e. the potential carry) will be
+-- removed by the caller if it is not already done by the backend.
+bignat_shiftr
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> Word#
+ -> State# RealWorld
+ -> State# RealWorld
+bignat_shiftr mwa wa n s = ioVoid (ghc_bignat_shiftr mwa wa n) s
+
+foreign import ccall unsafe ghc_bignat_shiftr
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> Word#
+ -> IO ()
+
+-- | Right-shift a non-zero BigNat by a non-zero amount of bits by first
+-- converting it into its two's complement representation and then again after
+-- the arithmetic shift.
+--
+-- Result is to be stored in the MutableWordArray#.
+-- The latter has size: required limbs
+--
+-- The potential 0 most-significant Words (i.e. the potential carry) will be
+-- removed by the caller if it is not already done by the backend.
+bignat_shiftr_neg
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> Word#
+ -> State# RealWorld
+ -> State# RealWorld
+bignat_shiftr_neg mwa wa n s = ioVoid (ghc_bignat_shiftr_neg mwa wa n) s
+
+foreign import ccall unsafe ghc_bignat_shiftr_neg
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> Word#
+ -> IO ()
+
+
+-- | OR two non-zero BigNat
+--
+-- Result is to be stored in the MutableWordArray#.
+-- The latter has size: max (size a, size b)
+bignat_or
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> State# RealWorld
+ -> State# RealWorld
+{-# INLINE bignat_or #-}
+bignat_or mwa wa wb s = ioVoid (ghc_bignat_or mwa wa wb) s
+
+foreign import ccall unsafe ghc_bignat_or
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> IO ()
+
+-- | XOR two non-zero BigNat
+--
+-- Result is to be stored in the MutableWordArray#.
+-- The latter has size: max (size a, size b)
+--
+-- The potential 0 most-significant Words will be removed by the caller if it is
+-- not already done by the backend.
+bignat_xor
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> State# RealWorld
+ -> State# RealWorld
+{-# INLINE bignat_xor #-}
+bignat_xor mwa wa wb s = ioVoid (ghc_bignat_xor mwa wa wb) s
+
+foreign import ccall unsafe ghc_bignat_xor
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> IO ()
+
+-- | AND two non-zero BigNat
+--
+-- Result is to be stored in the MutableWordArray#.
+-- The latter has size: min (size a, size b)
+--
+-- The potential 0 most-significant Words will be removed by the caller if it is
+-- not already done by the backend.
+bignat_and
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> State# RealWorld
+ -> State# RealWorld
+{-# INLINE bignat_and #-}
+bignat_and mwa wa wb s = ioVoid (ghc_bignat_and mwa wa wb) s
+
+foreign import ccall unsafe ghc_bignat_and
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> IO ()
+
+-- | ANDNOT two non-zero BigNat
+--
+-- Result is to be stored in the MutableWordArray#.
+-- The latter has size: size a
+--
+-- The potential 0 most-significant Words will be removed by the caller if it is
+-- not already done by the backend.
+bignat_and_not
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> State# RealWorld
+ -> State# RealWorld
+{-# INLINE bignat_and_not #-}
+bignat_and_not mwa wa wb s = ioVoid (ghc_bignat_and_not mwa wa wb) s
+
+foreign import ccall unsafe ghc_bignat_and_not
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> IO ()
+
+-- | QuotRem of two non-zero BigNat
+--
+-- Result quotient and remainder are to be stored in the MutableWordArray#.
+-- The first one (quotient) has size: size(A)-size(B)+1
+-- The second one (remainder) has size: size(b)
+--
+-- The potential 0 most-significant Words will be removed by the caller if it is
+-- not already done by the backend.
+bignat_quotrem
+ :: MutableWordArray# RealWorld -- ^ Quotient
+ -> MutableWordArray# RealWorld -- ^ Remainder
+ -> WordArray#
+ -> WordArray#
+ -> State# RealWorld
+ -> State# RealWorld
+bignat_quotrem mwq mwr wa wb s =
+ ioVoid (ghc_bignat_quotrem mwq mwr wa wb) s
+
+foreign import ccall unsafe ghc_bignat_quotrem
+ :: MutableWordArray# RealWorld
+ -> MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> IO ()
+
+-- | Quotient of two non-zero BigNat
+--
+-- Result quotient is to be stored in the MutableWordArray#.
+-- The latter has size: size(A)-size(B)+1
+--
+-- The potential 0 most-significant Words will be removed by the caller if it is
+-- not already done by the backend.
+bignat_quot
+ :: MutableWordArray# RealWorld -- ^ Quotient
+ -> WordArray#
+ -> WordArray#
+ -> State# RealWorld
+ -> State# RealWorld
+bignat_quot mwq wa wb s =
+ ioVoid (ghc_bignat_quot mwq wa wb) s
+
+foreign import ccall unsafe ghc_bignat_quot
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> IO ()
+
+-- | Remainder of two non-zero BigNat
+--
+-- Result remainder is to be stored in the MutableWordArray#.
+-- The latter has size: size(B)
+--
+-- The potential 0 most-significant Words will be removed by the caller if it is
+-- not already done by the backend.
+bignat_rem
+ :: MutableWordArray# RealWorld -- ^ Quotient
+ -> WordArray#
+ -> WordArray#
+ -> State# RealWorld
+ -> State# RealWorld
+bignat_rem mwr wa wb s =
+ ioVoid (ghc_bignat_rem mwr wa wb) s
+
+foreign import ccall unsafe ghc_bignat_rem
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> IO ()
+
+-- | QuotRem of a non-zero BigNat and a non-zero Word
+--
+-- Result quotient is to be stored in the MutableWordArray#.
+-- The latter has size: size(A)
+--
+-- The remainder is returned.
+--
+-- The potential 0 most-significant Words will be removed by the caller if it is
+-- not already done by the backend.
+bignat_quotrem_word
+ :: MutableWordArray# RealWorld -- ^ Quotient
+ -> WordArray#
+ -> Word#
+ -> State# RealWorld
+ -> (# State# RealWorld, Word# #)
+bignat_quotrem_word mwq wa b s =
+ ioWord# (ghc_bignat_quotrem_word mwq wa b) s
+
+foreign import ccall unsafe ghc_bignat_quotrem_word
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> Word#
+ -> IO Word
+
+-- | Quot of a non-zero BigNat and a non-zero Word
+--
+-- Result quotient is to be stored in the MutableWordArray#.
+-- The latter has size: size(A)
+--
+-- The potential 0 most-significant Words will be removed by the caller if it is
+-- not already done by the backend.
+bignat_quot_word
+ :: MutableWordArray# RealWorld -- ^ Quotient
+ -> WordArray#
+ -> Word#
+ -> State# RealWorld
+ -> State# RealWorld
+bignat_quot_word mwq wa b s =
+ ioVoid (ghc_bignat_quot_word mwq wa b) s
+
+foreign import ccall unsafe ghc_bignat_quot_word
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> Word#
+ -> IO ()
+
+-- | Remainder of a non-zero BigNat and a non-zero Word
+--
+-- The remainder is returned.
+bignat_rem_word
+ :: WordArray#
+ -> Word#
+ -> Word#
+bignat_rem_word = ghc_bignat_rem_word
+
+foreign import ccall unsafe ghc_bignat_rem_word
+ :: WordArray#
+ -> Word#
+ -> Word#
+
+
+-- | Greatest common divisor (GCD) of two non-zero and non-one BigNat
+--
+-- Result GCD is to be stored in the MutableWordArray#.
+-- The latter has size: size(B)
+-- The first WordArray# is greater than the second WordArray#.
+--
+-- The potential 0 most-significant Words will be removed by the caller if it is
+-- not already done by the backend.
+bignat_gcd
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> State# RealWorld
+ -> State# RealWorld
+bignat_gcd mwr wa wb s =
+ ioVoid (ghc_bignat_gcd mwr wa wb) s
+
+foreign import ccall unsafe ghc_bignat_gcd
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> IO ()
+
+-- | Greatest common divisor (GCD) of a non-zero/non-one BigNat and a
+-- non-zero/non-one Word#
+--
+-- Result GCD is returned
+bignat_gcd_word
+ :: WordArray#
+ -> Word#
+ -> Word#
+bignat_gcd_word = ghc_bignat_gcd_word
+
+foreign import ccall unsafe ghc_bignat_gcd_word
+ :: WordArray#
+ -> Word#
+ -> Word#
+
+-- | Greatest common divisor (GCD) of two Word#
+--
+-- Result GCD is returned
+bignat_gcd_word_word
+ :: Word#
+ -> Word#
+ -> Word#
+bignat_gcd_word_word = ghc_bignat_gcd_word_word
+
+foreign import ccall unsafe ghc_bignat_gcd_word_word
+ :: Word#
+ -> Word#
+ -> Word#
+
+-- | Encode (# BigNat mantissa, Int# exponent #) into a Double#
+bignat_encode_double :: WordArray# -> Int# -> Double#
+bignat_encode_double = ghc_bignat_encode_double
+
+foreign import ccall unsafe ghc_bignat_encode_double
+ :: WordArray#
+ -> Int#
+ -> Double#
+
+-- | \"@'bignat_powmod_word' /b/ /e/ /m/@\" computes base @/b/@ raised to
+-- exponent @/e/@ modulo @/m/@.
+--
+-- b > 1
+-- e > 0
+-- m > 1
+bignat_powmod_word :: WordArray# -> WordArray# -> Word# -> Word#
+bignat_powmod_word = ghc_bignat_powmod_word
+
+foreign import ccall unsafe ghc_bignat_powmod_word
+ :: WordArray# -> WordArray# -> Word# -> Word#
+
+-- | \"@'bignat_powmod' r /b/ /e/ /m/@\" computes base @/b/@ raised to
+-- exponent @/e/@ modulo @/m/@.
+--
+-- b > 1
+-- e > 0
+-- m > 1
+--
+-- Result is to be stored in the MutableWordArray# (which size is equal to the
+-- one of m).
+--
+-- The potential 0 most-significant Words will be removed by the caller if it is
+-- not already done by the backend.
+bignat_powmod
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> WordArray#
+ -> State# RealWorld
+ -> State# RealWorld
+bignat_powmod r b e m s =
+ ioVoid (ghc_bignat_powmod r b e m) s
+
+foreign import ccall unsafe ghc_bignat_powmod
+ :: MutableWordArray# RealWorld
+ -> WordArray#
+ -> WordArray#
+ -> WordArray#
+ -> IO ()
+
+-- | \"@'bignat_powmod' /b/ /e/ /m/@\" computes base @/b/@ raised to
+-- exponent @/e/@ modulo @/m/@.
+--
+-- b > 1
+-- e > 0
+-- m > 1
+bignat_powmod_words
+ :: Word#
+ -> Word#
+ -> Word#
+ -> Word#
+bignat_powmod_words = ghc_bignat_powmod_words
+
+foreign import ccall unsafe ghc_bignat_powmod_words
+ :: Word# -> Word# -> Word# -> Word#
+