diff options
author | Sylvain Henry <sylvain@haskus.fr> | 2020-09-25 18:29:21 +0200 |
---|---|---|
committer | Sylvain Henry <sylvain@haskus.fr> | 2020-09-28 09:56:49 +0200 |
commit | ebcc09687b8d84daf00987a466834a20a9831e7b (patch) | |
tree | 7fdc8ee5a237874af41a81066c5b9d4c4d20c18e | |
parent | 74f3f581dd04cbb1018feeb1a4afb32944152387 (diff) | |
download | haskell-ebcc09687b8d84daf00987a466834a20a9831e7b.tar.gz |
Bignum: add bigNatFromWordArray
Reimplementation of integer-gmp's byteArrayToBigNat#
-rw-r--r-- | libraries/ghc-bignum/src/GHC/Num/BigNat.hs | 39 | ||||
-rw-r--r-- | libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs | 6 |
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 f6e2fd6b1f..e435715295 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# void# + + | 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) |