summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2020-09-25 18:29:21 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-09-26 05:37:23 -0400
commit1cde295c543e209c3b81256b50e77f3c5132a4ad (patch)
tree0e6412746803f6e73dcc77963994fef43c2ae28e
parentf08f98e821bc4b755a7b6ad3bad39ce1099c5405 (diff)
downloadhaskell-1cde295c543e209c3b81256b50e77f3c5132a4ad.tar.gz
Bignum: add bigNatFromWordArray
Reimplementation of integer-gmp's byteArrayToBigNat#
-rw-r--r--libraries/ghc-bignum/src/GHC/Num/BigNat.hs39
-rw-r--r--libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs6
2 files changed, 45 insertions, 0 deletions
diff --git a/libraries/ghc-bignum/src/GHC/Num/BigNat.hs b/libraries/ghc-bignum/src/GHC/Num/BigNat.hs
index f2d9e58e17..b2a84b323c 100644
--- a/libraries/ghc-bignum/src/GHC/Num/BigNat.hs
+++ b/libraries/ghc-bignum/src/GHC/Num/BigNat.hs
@@ -1520,3 +1520,42 @@ bigNatFromByteArrayBE# sz ba moff s =
bigNatFromByteArray# :: Word# -> ByteArray# -> Word# -> Bool# -> State# s -> (# State# s, BigNat# #)
bigNatFromByteArray# sz ba off 0# s = bigNatFromByteArrayLE# sz ba off s
bigNatFromByteArray# sz ba off _ s = bigNatFromByteArrayBE# sz ba off s
+
+
+
+
+-- | Create a BigNat# from a WordArray# containing /n/ limbs in
+-- least-significant-first order.
+--
+-- If possible 'WordArray#', will be used directly (i.e. shared
+-- /without/ cloning the 'WordArray#' into a newly allocated one)
+bigNatFromWordArray# :: WordArray# -> Word# -> BigNat#
+bigNatFromWordArray# wa n0
+ | isTrue# (n `eqWord#` 0##)
+ = bigNatZero# (# #)
+
+ | isTrue# (r `eqWord#` 0##) -- i.e. wa is multiple of limb-size
+ , isTrue# (q `eqWord#` n)
+ = wa
+
+ | True = withNewWordArray# (word2Int# n) \mwa s ->
+ mwaArrayCopy# mwa 0# wa 0# (word2Int# n) s
+ where
+ !(# q, r #) = quotRemWord# (int2Word# (sizeofByteArray# wa))
+ WORD_SIZE_IN_BYTES##
+ -- find real size in Words by removing trailing null limbs
+ !n = real_size n0
+ real_size 0## = 0##
+ real_size i
+ | 0## <- bigNatIndex# wa (word2Int# (i `minusWord#` 1##))
+ = real_size (i `minusWord#` 1##)
+ real_size i = i
+
+
+-- | Create a BigNat from a WordArray# containing /n/ limbs in
+-- least-significant-first order.
+--
+-- If possible 'WordArray#', will be used directly (i.e. shared
+-- /without/ cloning the 'WordArray#' into a newly allocated one)
+bigNatFromWordArray :: WordArray# -> Word# -> BigNat
+bigNatFromWordArray wa n = BN# (bigNatFromWordArray# wa n)
diff --git a/libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs b/libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs
index 3d5fabe6c0..a501196e67 100644
--- a/libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs
+++ b/libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs
@@ -53,6 +53,7 @@ module GHC.Integer.GMP.Internals
-- ** Conversions to/from 'BigNat'
+ , byteArrayToBigNat#
, wordToBigNat
, wordToBigNat2
, bigNatToInt
@@ -432,3 +433,8 @@ importIntegerFromByteArray ba off sz endian = case runRW# (I.integerFromByteArra
exportIntegerToMutableByteArray :: Integer -> MutableByteArray# RealWorld -> Word# -> Int# -> IO Word
exportIntegerToMutableByteArray i mba off endian = IO (\s -> case I.integerToMutableByteArray# i mba off endian s of
(# s', r #) -> (# s', W# r #))
+
+
+{-# DEPRECATED byteArrayToBigNat# "Use bigNatFromWordArray instead" #-}
+byteArrayToBigNat# :: ByteArray# -> GmpSize# -> BigNat
+byteArrayToBigNat# ba n = B.bigNatFromWordArray ba (int2Word# n)