ghc-bignum 1.2 → 1.3
raw patch · 12 files changed
+465/−112 lines, 12 filesdep ~ghc-primPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: ghc-prim
API changes (from Hackage documentation)
- GHC.Num.Integer: integerCompare' :: Integer -> Integer -> Ordering
- GHC.Num.WordArray: withNewWordArray2Trimed# :: Int# -> Int# -> (MutableWordArray# RealWorld -> MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld) -> (# WordArray#, WordArray# #)
- GHC.Num.WordArray: withNewWordArrayTrimed# :: Int# -> (MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld) -> WordArray#
- GHC.Num.WordArray: withNewWordArrayTrimedMaybe# :: Int# -> (MutableWordArray# RealWorld -> State# RealWorld -> (# State# RealWorld, Bool# #)) -> (# (# #) | WordArray# #)
+ GHC.Num.Backend.Native: backendName :: [Char]
+ GHC.Num.Backend.Selected: backendName :: [Char]
+ GHC.Num.BigNat: bigNatFromWord64# :: Word64# -> BigNat#
+ GHC.Num.BigNat: bigNatToWord64# :: BigNat# -> Word64#
+ GHC.Num.Integer: integerFromWord64# :: Word64# -> Integer
+ GHC.Num.Integer: integerToInt64# :: Integer -> Int64#
+ GHC.Num.Integer: integerToWord64# :: Integer -> Word64#
+ GHC.Num.Natural: naturalClearBit :: Natural -> Word -> Natural
+ GHC.Num.Natural: naturalClearBit# :: Natural -> Word# -> Natural
+ GHC.Num.Natural: naturalComplementBit :: Natural -> Word -> Natural
+ GHC.Num.Natural: naturalComplementBit# :: Natural -> Word# -> Natural
+ GHC.Num.Natural: naturalSetBit :: Natural -> Word -> Natural
+ GHC.Num.Natural: naturalSetBit# :: Natural -> Word# -> Natural
+ GHC.Num.WordArray: withNewWordArray2Trimmed# :: Int# -> Int# -> (MutableWordArray# RealWorld -> MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld) -> (# WordArray#, WordArray# #)
+ GHC.Num.WordArray: withNewWordArrayTrimmed# :: Int# -> (MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld) -> WordArray#
+ GHC.Num.WordArray: withNewWordArrayTrimmedMaybe# :: Int# -> (MutableWordArray# RealWorld -> State# RealWorld -> (# State# RealWorld, Bool# #)) -> (# (# #) | WordArray# #)
- GHC.Num.Integer: IN :: !BigNat# -> Integer
+ GHC.Num.Integer: IN :: ByteArray# -> Integer
- GHC.Num.Integer: IP :: !BigNat# -> Integer
+ GHC.Num.Integer: IP :: ByteArray# -> Integer
- GHC.Num.Integer: IS :: !Int# -> Integer
+ GHC.Num.Integer: IS :: Int# -> Integer
- GHC.Num.Integer: integerFromInt64# :: Int# -> Integer
+ GHC.Num.Integer: integerFromInt64# :: Int64# -> Integer
- GHC.Num.Natural: NB :: !BigNat# -> Natural
+ GHC.Num.Natural: NB :: ByteArray# -> Natural
- GHC.Num.Natural: NS :: !Word# -> Natural
+ GHC.Num.Natural: NS :: Word# -> Natural
Files
- changelog.md +5/−0
- configure +13/−1
- ghc-bignum.cabal +2/−2
- src/GHC/Num/Backend/Check.hs +7/−0
- src/GHC/Num/Backend/FFI.hs +4/−0
- src/GHC/Num/Backend/GMP.hs +4/−0
- src/GHC/Num/Backend/Native.hs +9/−4
- src/GHC/Num/BigNat.hs +67/−29
- src/GHC/Num/Integer.hs +301/−55
- src/GHC/Num/Natural.hs +47/−14
- src/GHC/Num/Primitives.hs +0/−1
- src/GHC/Num/WordArray.hs +6/−6
changelog.md view
@@ -1,5 +1,10 @@ # Changelog for `ghc-bignum` package +## 1.3++- Expose backendName+- Add `naturalSetBit[#]` (#21173), `naturalClearBit[#]` (#21175), `naturalComplementBit[#]` (#21181)+ ## 1.2 - Moved naturalToDouble# and naturalToFloat# to `base` package
configure view
@@ -664,6 +664,7 @@ docdir oldincludedir includedir+runstatedir localstatedir sharedstatedir sysconfdir@@ -739,6 +740,7 @@ sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var'+runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'@@ -991,6 +993,15 @@ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \+ | --runstate | --runstat | --runsta | --runst | --runs \+ | --run | --ru | --r)+ ac_prev=runstatedir ;;+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \+ | --run=* | --ru=* | --r=*)+ runstatedir=$ac_optarg ;;+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \@@ -1128,7 +1139,7 @@ for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \- libdir localedir mandir+ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes.@@ -1281,6 +1292,7 @@ --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var]+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include]
ghc-bignum.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.0 name: ghc-bignum-version: 1.2+version: 1.3 synopsis: GHC BigNum library license: BSD3 license-file: LICENSE@@ -77,7 +77,7 @@ ForeignFunctionInterface build-depends:- ghc-prim >= 0.5.1.0 && < 0.9+ ghc-prim >= 0.5.1.0 && < 0.10 hs-source-dirs: src/ include-dirs: include/
src/GHC/Num/Backend/Check.hs view
@@ -12,6 +12,7 @@ -- | Check Native implementation against another backend module GHC.Num.Backend.Check where +import GHC.CString import GHC.Prim import GHC.Types import GHC.Num.WordArray@@ -26,6 +27,12 @@ #endif default ()++-- | ghc-bignum backend name+backendName :: [Char]+backendName = unpackAppendCString# "check-"# Other.backendName+ -- we don't have (++) at our disposal, so we directly use+ -- `unpackAppendCString#` bignat_compare :: WordArray#
src/GHC/Num/Backend/FFI.hs view
@@ -25,6 +25,10 @@ default () +-- | ghc-bignum backend name+backendName :: [Char]+backendName = "ffi"+ -- | Compare two non-zero BigNat of the same length -- -- Return:
src/GHC/Num/Backend/GMP.hs view
@@ -32,6 +32,10 @@ default () +-- | ghc-bignum backend name+backendName :: [Char]+backendName = "gmp"+ ---------------------------------------------------------------------------- -- type definitions
src/GHC/Num/Backend/Native.hs view
@@ -30,6 +30,11 @@ default () +-- | ghc-bignum backend name+backendName :: [Char]+backendName = "native"++ count_words_bits :: Word# -> (# Word#, Word# #) count_words_bits n = (# nw, nb #) where@@ -182,8 +187,8 @@ !ctzB = word2Int# (bigNatCtzWord# wb) -- multiply a single bj Word# to the whole wa WordArray- mul bj j i carry s- | isTrue# (i ==# szA)+ mul mwa wa bj j i carry s+ | isTrue# (i ==# wordArraySize# wa) -- write the carry = mwaAddInplaceWord# mwa (i +# j) carry s @@ -193,7 +198,7 @@ !(# c'',r #) = plusWord2# r' carry carry' = plusWord# c' c'' in case mwaAddInplaceWord# mwa (i +# j) r s of- s' -> mul bj j (i +# 1#) carry' s'+ s' -> mul mwa wa bj j (i +# 1#) carry' s' -- for each bj in wb, call `mul bj wa` mulEachB i s@@ -201,7 +206,7 @@ | True = case indexWordArray# wb i of -- detect bj == 0## and skip the loop 0## -> mulEachB (i +# 1#) s- bi -> case mul bi i ctzA 0## s of+ bi -> case mul mwa wa bi i ctzA 0## s of s' -> mulEachB (i +# 1#) s' bignat_sub
src/GHC/Num/BigNat.hs view
@@ -263,6 +263,16 @@ in uncheckedShiftL64# wh 32# `or64#` wl else wl +#else++-- | Convert a Word64# into a BigNat on 64-bit architectures+bigNatFromWord64# :: Word64# -> BigNat#+bigNatFromWord64# w64 = bigNatFromWord# (word64ToWord# w64)++-- | Convert a BigNat into a Word64# on 64-bit architectures+bigNatToWord64# :: BigNat# -> Word64#+bigNatToWord64# b = wordToWord64# (bigNatToWord# b)+ #endif -- | Encode (# BigNat mantissa, Int# exponent #) into a Double#@@ -312,6 +322,7 @@ -- | Equality test for BigNat bigNatEq# :: BigNat# -> BigNat# -> Bool#+{-# NOINLINE bigNatEq# #-} bigNatEq# wa wb | isTrue# (wordArraySize# wa /=# wordArraySize# wb) = 0# | isTrue# (wordArraySize# wa ==# 0#) = 1#@@ -331,6 +342,7 @@ -- | Compare a BigNat and a Word# bigNatCompareWord# :: BigNat# -> Word# -> Ordering+{-# NOINLINE bigNatCompareWord# #-} bigNatCompareWord# a b | bigNatIsZero a = cmpW# 0## b | isTrue# (wordArraySize# a ># 1#) = GT@@ -343,6 +355,7 @@ -- | Compare two BigNat bigNatCompare :: BigNat# -> BigNat# -> Ordering+{-# NOINLINE bigNatCompare #-} bigNatCompare a b = let szA = wordArraySize# a@@ -408,7 +421,7 @@ = bigNatFromWord# b | True- = withNewWordArrayTrimed# (wordArraySize# a +# 1#) \mwa s ->+ = withNewWordArrayTrimmed# (wordArraySize# a +# 1#) \mwa s -> inline bignat_add_word mwa a b s -- | Add a bigNat and a Word@@ -426,7 +439,7 @@ !szB = wordArraySize# b !szMax = maxI# szA szB !sz = szMax +# 1# -- for the potential carry- in withNewWordArrayTrimed# sz \mwa s ->+ in withNewWordArrayTrimmed# sz \mwa s -> inline bignat_add mwa a b s -------------------------------------------------@@ -443,7 +456,7 @@ | isTrue# (bigNatSize# a ==# 1#) = case timesWord2# (bigNatIndex# a 0#) w of (# h, l #) -> bigNatFromWord2# h l- | True = withNewWordArrayTrimed# (bigNatSize# a +# 1#) \mwa s ->+ | True = withNewWordArrayTrimmed# (bigNatSize# a +# 1#) \mwa s -> inline bignat_mul_word mwa a w s -- | Multiply a BigNAt by a Word@@ -469,7 +482,7 @@ !szA = wordArraySize# a !szB = wordArraySize# b !sz = szA +# szB- in withNewWordArrayTrimed# sz \mwa s->+ in withNewWordArrayTrimmed# sz \mwa s-> inline bignat_mul mwa a b s @@ -483,7 +496,7 @@ bigNatSubWordUnsafe# :: BigNat# -> Word# -> BigNat# bigNatSubWordUnsafe# x y | 0## <- y = x- | True = withNewWordArrayTrimed# sz \mwa -> go mwa y 0#+ | True = withNewWordArrayTrimmed# sz \mwa -> go mwa y 0# where !sz = wordArraySize# x @@ -511,7 +524,7 @@ | 0## <- b = (# | a #) | bigNatIsZero a = (# (# #) | #) | True- = withNewWordArrayTrimedMaybe# (bigNatSize# a) \mwa s ->+ = withNewWordArrayTrimmedMaybe# (bigNatSize# a) \mwa s -> inline bignat_sub_word mwa a b s @@ -521,7 +534,7 @@ | bigNatIsZero b = a | True = let szA = wordArraySize# a- in withNewWordArrayTrimed# szA \mwa s->+ in withNewWordArrayTrimmed# szA \mwa s-> case inline bignat_sub mwa a b s of (# s', 1# #) -> s' (# s', _ #) -> case raiseUnderflow of@@ -537,7 +550,7 @@ = (# (# #) | #) | True- = withNewWordArrayTrimedMaybe# (bigNatSize# a) \mwa s ->+ = withNewWordArrayTrimmedMaybe# (bigNatSize# a) \mwa s -> inline bignat_sub mwa a b s @@ -556,7 +569,7 @@ | True = let sz = wordArraySize# a- in withNewWordArrayTrimed# sz \mwq s ->+ in withNewWordArrayTrimmed# sz \mwq s -> inline bignat_quot_word mwq a b s -- | Divide a BigNat by a Word, return the quotient@@ -628,7 +641,7 @@ | isTrue# (szB ==# 1#) = case bigNatQuotRemWord# a (bigNatIndex# b 0#) of (# q, r #) -> (# q, bigNatFromWord# r #) - | True = withNewWordArray2Trimed# szQ szR \mwq mwr s ->+ | True = withNewWordArray2Trimmed# szQ szR \mwq mwr s -> inline bignat_quotrem mwq mwr a b s where cmp = bigNatCompare a b@@ -647,7 +660,7 @@ | LT <- cmp = bigNatZero# (# #) | EQ <- cmp = bigNatOne# (# #) | isTrue# (szB ==# 1#) = bigNatQuotWord# a (bigNatIndex# b 0#)- | True = withNewWordArrayTrimed# szQ \mwq s ->+ | True = withNewWordArrayTrimmed# szQ \mwq s -> inline bignat_quot mwq a b s where cmp = bigNatCompare a b@@ -665,7 +678,7 @@ | EQ <- cmp = bigNatZero# (# #) | isTrue# (szB ==# 1#) = case bigNatRemWord# a (bigNatIndex# b 0#) of r -> bigNatFromWord# r- | True = withNewWordArrayTrimed# szR \mwr s ->+ | True = withNewWordArrayTrimmed# szR \mwr s -> inline bignat_rem mwr a b s where cmp = bigNatCompare a b@@ -719,7 +732,7 @@ _ -> let go wx wy = -- wx > wy- withNewWordArrayTrimed# (wordArraySize# wy) \mwr s ->+ withNewWordArrayTrimmed# (wordArraySize# wy) \mwr s -> bignat_gcd mwr wx wy s in case bigNatCompare a b of EQ -> a@@ -808,7 +821,7 @@ bigNatAnd a b | bigNatIsZero a = a | bigNatIsZero b = b- | True = withNewWordArrayTrimed# sz \mwa s ->+ | True = withNewWordArrayTrimmed# sz \mwa s -> inline bignat_and mwa a b s where !szA = wordArraySize# a@@ -820,7 +833,7 @@ bigNatAndNot a b | bigNatIsZero a = a | bigNatIsZero b = a- | True = withNewWordArrayTrimed# szA \mwa s ->+ | True = withNewWordArrayTrimmed# szA \mwa s -> inline bignat_and_not mwa a b s where !szA = wordArraySize# a@@ -860,7 +873,7 @@ bigNatXor a b | bigNatIsZero a = b | bigNatIsZero b = a- | True = withNewWordArrayTrimed# sz \mwa s ->+ | True = withNewWordArrayTrimmed# sz \mwa s -> inline bignat_xor mwa a b s where !szA = wordArraySize# a@@ -907,7 +920,7 @@ !szA = wordArraySize# a !nw = word2Int# (n `uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#) !sz = szA -# nw- in withNewWordArrayTrimed# sz \mwa s ->+ in withNewWordArrayTrimmed# sz \mwa s -> inline bignat_shiftr mwa a n s -- | Bit shift right (two's complement)@@ -928,7 +941,7 @@ !szA = wordArraySize# a !nw = (word2Int# n -# 1#) `uncheckedIShiftRL#` WORD_SIZE_BITS_SHIFT# !sz = szA -# nw- in withNewWordArrayTrimed# sz \mwa s ->+ in withNewWordArrayTrimmed# sz \mwa s -> inline bignat_shiftr_neg mwa a n s @@ -956,7 +969,7 @@ !nb = word2Int# (n `and#` WORD_SIZE_BITS_MASK##) !sz = szA +# nw +# (nb /=# 0#) - in withNewWordArrayTrimed# sz \mwa s ->+ in withNewWordArrayTrimmed# sz \mwa s -> inline bignat_shiftl mwa a n s @@ -1032,6 +1045,7 @@ -- | BigNat set bit bigNatSetBit# :: BigNat# -> Word# -> BigNat#+{-# NOINLINE bigNatSetBit# #-} bigNatSetBit# a n -- check the current bit value | isTrue# (bigNatTestBit# a n) = a@@ -1056,10 +1070,25 @@ -- | Reverse the given bit bigNatComplementBit# :: BigNat# -> Word# -> BigNat#-bigNatComplementBit# bn i- | isTrue# (bigNatTestBit# bn i) = bigNatClearBit# bn i- | True = bigNatSetBit# bn i+bigNatComplementBit# a n =+ let+ !sz = wordArraySize# a+ !nw = word2Int# (n `uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)+ !nb = word2Int# (n `and#` WORD_SIZE_BITS_MASK##)+ d = nw +# 1# -# sz+ in if+ -- result BigNat will have more limbs+ | isTrue# (d ># 0#)+ -> withNewWordArray# (nw +# 1#) \mwa s ->+ case mwaArrayCopy# mwa 0# a 0# sz s of+ s' -> case mwaFill# mwa 0## (int2Word# sz) (int2Word# (d -# 1#)) s' of+ s'' -> writeWordArray# mwa nw (bitW# nb) s'' + | nv <- bigNatIndex# a nw `xor#` bitW# nb+ -> withNewWordArrayTrimmed# sz \mwa s ->+ case mwaArrayCopy# mwa 0# a 0# sz s of+ s' -> writeWordArray# mwa nw nv s'+ ------------------------------------------------- -- Log operations -------------------------------------------------@@ -1175,7 +1204,7 @@ | bigNatIsZero e = bigNatFromWord# 1## | bigNatIsZero b = bigNatFromWord# 0## | bigNatIsOne b = bigNatFromWord# 1##- | True = withNewWordArrayTrimed# (bigNatSize# m) \mwa s ->+ | True = withNewWordArrayTrimmed# (bigNatSize# m) \mwa s -> inline bignat_powmod mwa b e m s -- | Return count of trailing zero bits@@ -1226,6 +1255,7 @@ -- written in advance. In case of @/i/ == 0@, the function will write and report -- zero bytes written. bigNatToAddrLE# :: BigNat# -> Addr# -> State# s -> (# State# s, Word# #)+{-# NOINLINE bigNatToAddrLE# #-} bigNatToAddrLE# a addr s0 | isTrue# (sz ==# 0#) = (# s0, 0## #) | True = case writeMSB s0 of@@ -1255,6 +1285,7 @@ -- written in advance. In case of @/i/ == 0@, the function will write and report -- zero bytes written. bigNatToAddrBE# :: BigNat# -> Addr# -> State# s -> (# State# s, Word# #)+{-# NOINLINE bigNatToAddrBE# #-} bigNatToAddrBE# a addr s0 | isTrue# (sz ==# 0#) = (# s0, 0## #) | msw <- indexWordArray# a (sz -# 1#)@@ -1312,8 +1343,9 @@ -- -- The size is given in bytes. ----- Higher limbs equal to 0 are automatically trimed.+-- Higher limbs equal to 0 are automatically trimmed. bigNatFromAddrLE# :: Word# -> Addr# -> State# s -> (# State# s, BigNat# #)+{-# NOINLINE bigNatFromAddrLE# #-} bigNatFromAddrLE# 0## _ s = (# s, bigNatZero# (# #) #) bigNatFromAddrLE# sz addr s = let@@ -1347,8 +1379,9 @@ -- -- The size is given in bytes. ----- Null higher limbs are automatically trimed.+-- Null higher limbs are automatically trimmed. bigNatFromAddrBE# :: Word# -> Addr# -> State# s -> (# State# s, BigNat# #)+{-# NOINLINE bigNatFromAddrBE# #-} bigNatFromAddrBE# 0## _ s = (# s, bigNatZero# (# #) #) bigNatFromAddrBE# sz addr s = let@@ -1387,7 +1420,7 @@ -- byte first (big-endian) if @1#@ or least significant byte first -- (little-endian) if @0#@. ----- Null higher limbs are automatically trimed.+-- Null higher limbs are automatically trimmed. bigNatFromAddr# :: Word# -> Addr# -> Bool# -> State# s -> (# State# s, BigNat# #) bigNatFromAddr# sz addr 0# s = bigNatFromAddrLE# sz addr s bigNatFromAddr# sz addr _ s = bigNatFromAddrBE# sz addr s@@ -1403,6 +1436,7 @@ -- written in advance. In case of @/i/ == 0@, the function will write and report -- zero bytes written. bigNatToMutableByteArrayLE# :: BigNat# -> MutableByteArray# s -> Word# -> State# s -> (# State# s, Word# #)+{-# NOINLINE bigNatToMutableByteArrayLE# #-} bigNatToMutableByteArrayLE# a mba moff s0 | isTrue# (sz ==# 0#) = (# s0, 0## #) | True = case writeMSB s0 of@@ -1432,6 +1466,7 @@ -- written in advance. In case of @/i/ == 0@, the function will write and report -- zero bytes written. bigNatToMutableByteArrayBE# :: BigNat# -> MutableByteArray# s -> Word# -> State# s -> (# State# s, Word# #)+{-# NOINLINE bigNatToMutableByteArrayBE# #-} bigNatToMutableByteArrayBE# a mba moff s0 | isTrue# (sz ==# 0#) = (# s0, 0## #) | msw <- indexWordArray# a (sz -# 1#)@@ -1473,8 +1508,9 @@ -- -- The size is given in bytes. ----- Null higher limbs are automatically trimed.+-- Null higher limbs are automatically trimmed. bigNatFromByteArrayLE# :: Word# -> ByteArray# -> Word# -> State# s -> (# State# s, BigNat# #)+{-# NOINLINE bigNatFromByteArrayLE# #-} bigNatFromByteArrayLE# 0## _ _ s = (# s, bigNatZero# (# #) #) bigNatFromByteArrayLE# sz ba moff s = let@@ -1508,8 +1544,9 @@ -- -- The size is given in bytes. ----- Null higher limbs are automatically trimed.+-- Null higher limbs are automatically trimmed. bigNatFromByteArrayBE# :: Word# -> ByteArray# -> Word# -> State# s -> (# State# s, BigNat# #)+{-# NOINLINE bigNatFromByteArrayBE# #-} bigNatFromByteArrayBE# 0## _ _ s = (# s, bigNatZero# (# #) #) bigNatFromByteArrayBE# sz ba moff s = let@@ -1548,7 +1585,7 @@ -- byte first (big-endian) if @1#@ or least significant byte first -- (little-endian) if @0#@. ----- Null higher limbs are automatically trimed.+-- Null higher limbs are automatically trimmed. 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@@ -1562,6 +1599,7 @@ -- If possible 'WordArray#', will be used directly (i.e. shared -- /without/ cloning the 'WordArray#' into a newly allocated one) bigNatFromWordArray# :: WordArray# -> Word# -> BigNat#+{-# NOINLINE bigNatFromWordArray# #-} bigNatFromWordArray# wa n0 | isTrue# (n `eqWord#` 0##) = bigNatZero# (# #)
src/GHC/Num/Integer.hs view
@@ -194,7 +194,7 @@ integerFromNatural :: Natural -> Integer {-# NOINLINE integerFromNatural #-} integerFromNatural (NS x) = integerFromWord# x-integerFromNatural (NB x) = integerFromBigNat# x+integerFromNatural (NB x) = IP x -- | Convert a list of Word into an Integer integerFromWordList :: Bool -> [Word] -> Integer@@ -282,7 +282,6 @@ -- | Equal predicate. integerEq# :: Integer -> Integer -> Bool#-{-# NOINLINE integerEq# #-} integerEq# (IS x) (IS y) = x ==# y integerEq# (IN x) (IN y) = bigNatEq# x y integerEq# (IP x) (IP y) = bigNatEq# x y@@ -290,7 +289,6 @@ -- | Not-equal predicate. integerNe# :: Integer -> Integer -> Bool#-{-# NOINLINE integerNe# #-} integerNe# (IS x) (IS y) = x /=# y integerNe# (IN x) (IN y) = bigNatNe# x y integerNe# (IP x) (IP y) = bigNatNe# x y@@ -298,31 +296,27 @@ -- | Greater predicate. integerGt# :: Integer -> Integer -> Bool#-{-# NOINLINE integerGt# #-}-integerGt# (IS x) (IS y) = x ># y-integerGt# x y | GT <- integerCompare' x y = 1#-integerGt# _ _ = 0#+integerGt# (IS x) (IS y) = x ># y+integerGt# x y | GT <- integerCompare x y = 1#+integerGt# _ _ = 0# -- | Lower-or-equal predicate. integerLe# :: Integer -> Integer -> Bool#-{-# NOINLINE integerLe# #-}-integerLe# (IS x) (IS y) = x <=# y-integerLe# x y | GT <- integerCompare' x y = 0#-integerLe# _ _ = 1#+integerLe# (IS x) (IS y) = x <=# y+integerLe# x y | GT <- integerCompare x y = 0#+integerLe# _ _ = 1# -- | Lower predicate. integerLt# :: Integer -> Integer -> Bool#-{-# NOINLINE integerLt# #-}-integerLt# (IS x) (IS y) = x <# y-integerLt# x y | LT <- integerCompare' x y = 1#-integerLt# _ _ = 0#+integerLt# (IS x) (IS y) = x <# y+integerLt# x y | LT <- integerCompare x y = 1#+integerLt# _ _ = 0# -- | Greater-or-equal predicate. integerGe# :: Integer -> Integer -> Bool#-{-# NOINLINE integerGe# #-}-integerGe# (IS x) (IS y) = x >=# y-integerGe# x y | LT <- integerCompare' x y = 0#-integerGe# _ _ = 1#+integerGe# (IS x) (IS y) = x >=# y+integerGe# x y | LT <- integerCompare x y = 0#+integerGe# _ _ = 1# instance Eq Integer where (==) = integerEq@@ -330,20 +324,16 @@ -- | Compare two Integer integerCompare :: Integer -> Integer -> Ordering-{-# NOINLINE integerCompare #-}-integerCompare = integerCompare'--integerCompare' :: Integer -> Integer -> Ordering-{-# INLINE integerCompare' #-}-integerCompare' (IS x) (IS y) = compareInt# x y-integerCompare' (IP x) (IP y) = bigNatCompare x y-integerCompare' (IN x) (IN y) = bigNatCompare y x-integerCompare' (IS _) (IP _) = LT-integerCompare' (IS _) (IN _) = GT-integerCompare' (IP _) (IS _) = GT-integerCompare' (IN _) (IS _) = LT-integerCompare' (IP _) (IN _) = GT-integerCompare' (IN _) (IP _) = LT+{-# INLINEABLE integerCompare #-}+integerCompare (IS x) (IS y) = compareInt# x y+integerCompare (IP x) (IP y) = bigNatCompare x y+integerCompare (IN x) (IN y) = bigNatCompare y x+integerCompare (IS _) (IP _) = LT+integerCompare (IS _) (IN _) = GT+integerCompare (IP _) (IS _) = GT+integerCompare (IN _) (IS _) = LT+integerCompare (IP _) (IN _) = GT+integerCompare (IN _) (IP _) = LT instance Ord Integer where compare = integerCompare@@ -524,13 +514,11 @@ -- | Return @-1@, @0@, and @1@ depending on whether argument is -- negative, zero, or positive, respectively integerSignum :: Integer -> Integer-{-# NOINLINE integerSignum #-} integerSignum !j = IS (integerSignum# j) -- | Return @-1#@, @0#@, and @1#@ depending on whether argument is -- negative, zero, or positive, respectively integerSignum# :: Integer -> Int#-{-# NOINLINE integerSignum# #-} integerSignum# (IN _) = -1# integerSignum# (IS i#) = sgnI# i# integerSignum# (IP _ ) = 1#@@ -649,7 +637,7 @@ IS -1# -> IS -1# IS y -> IS (orI# x y) IP y- | isTrue# (x >=# 0#) -> integerFromBigNat# (bigNatOrWord# y (int2Word# x))+ | isTrue# (x >=# 0#) -> IP (bigNatOrWord# y (int2Word# x)) | True -> integerFromBigNatNeg# (bigNatAddWord# (bigNatAndNot -- use De Morgan's laws@@ -672,7 +660,7 @@ 1##) IP x -> case b of IS _ -> integerOr b a- IP y -> integerFromBigNat# (bigNatOr x y)+ IP y -> IP (bigNatOr x y) IN y -> integerFromBigNatNeg# (bigNatAddWord# (bigNatAndNot -- use De Morgan's laws@@ -1010,14 +998,12 @@ integerIsPowerOf2# (IN _) = (# (# #) | #) integerIsPowerOf2# (IP w) = bigNatIsPowerOf2# w -#if WORD_SIZE_IN_BITS == 32---- | Convert an Int64# into an Integer on 32-bit architectures+-- | Convert an Int64# into an Integer integerFromInt64# :: Int64# -> Integer {-# NOINLINE integerFromInt64# #-}-integerFromInt64# !i- | isTrue# ((i `leInt64#` intToInt64# 0x7FFFFFFF#)- &&# (i `geInt64#` intToInt64# -0x80000000#))+integerFromInt64# i+ | isTrue# ((i `leInt64#` intToInt64# INT_MAXBOUND#)+ &&# (i `geInt64#` intToInt64# INT_MINBOUND#)) = IS (int64ToInt# i) | isTrue# (i `geInt64#` intToInt64# 0#)@@ -1026,37 +1012,29 @@ | True = IN (bigNatFromWord64# (int64ToWord64# (negateInt64# i))) --- | Convert a Word64# into an Integer on 32-bit architectures+-- | Convert a Word64# into an Integer integerFromWord64# :: Word64# -> Integer {-# NOINLINE integerFromWord64# #-} integerFromWord64# !w- | isTrue# (w `leWord64#` wordToWord64# 0x7FFFFFFF##)+ | isTrue# (w `leWord64#` wordToWord64# INT_MAXBOUND##) = IS (int64ToInt# (word64ToInt64# w)) | True = IP (bigNatFromWord64# w) --- | Convert an Integer into an Int64# on 32-bit architectures+-- | Convert an Integer into an Int64# integerToInt64# :: Integer -> Int64# {-# NOINLINE integerToInt64# #-} integerToInt64# (IS i) = intToInt64# i integerToInt64# (IP b) = word64ToInt64# (bigNatToWord64# b) integerToInt64# (IN b) = negateInt64# (word64ToInt64# (bigNatToWord64# b)) --- | Convert an Integer into a Word64# on 32-bit architectures+-- | Convert an Integer into a Word64# integerToWord64# :: Integer -> Word64# {-# NOINLINE integerToWord64# #-} integerToWord64# (IS i) = int64ToWord64# (intToInt64# i) integerToWord64# (IP b) = bigNatToWord64# b integerToWord64# (IN b) = int64ToWord64# (negateInt64# (word64ToInt64# (bigNatToWord64# b))) -#else---- | Convert an Int64# into an Integer on 64-bit architectures-integerFromInt64# :: Int# -> Integer-integerFromInt64# !x = IS x--#endif- ---------------------------------------------------------------------------- -- Conversions to/from floating point ----------------------------------------------------------------------------@@ -1269,3 +1247,271 @@ -- e > 0 by cases above | True = (# Backend.integer_powmod b (integerToNatural e) m | #)+++{-+Note [Optimising conversions between numeric types]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Converting between numeric types is very common in Haskell codes. Suppose that+we have N inter-convertible numeric types (Word, Word8, Word32, Int, etc.).++- We don't want to have to use one conversion function per pair of types as that+would require N^2 functions: wordToWord8, wordToInt, word8ToWord32...++- The following kind of class would allow us to have a single conversion+function but at the price of N^2 instances and of the use of+MultiParamTypeClasses extension.++ class Convert a b where+ convert :: a -> b++So what we do instead is that we use the Integer type (signed, unbounded) as a+passthrough type to perform every conversion. Hence we only need to define two+functions per numeric type:++ class Integral a where+ toInteger :: a -> Integer++ class Num a where+ fromInteger :: Integer -> a++These classes have a single parameter and can be derived automatically (e.g. for+newtypes). So we don't even have to define 2*N instances. For example, all the+instances for the types in Foreign.C.Types (CChar, CShort, CInt, CUInt, etc.)+are automatically derived from the instances for Word, Int, Word8, Word16, etc.++Finally we can define a generic conversion function:++ -- in the Prelude+ fromIntegral :: (Integral a, Num b) => a -> b+ fromIntegral = fromInteger . toInteger++Efficient conversions+~~~~~~~~~~~~~~~~~~~~~++An issue with this approach is that performance might be terrible. E.g.+converting an Int into a Word, which is a no-op at the machine level, becomes+costly when performed via `fromIntegral` or any similar function because an+intermediate Integer has to be allocated in the heap to perform the conversion.++A solution is to bless one particular `fromIntegral`-like function and to use+rewrite rules to replace it with a more efficient function when both types are+known. This is what was done in the past, see next section. We use another+approach nowadays:++Notice that the set of primitive operations to convert from and to Integer and+Natural is pretty small:++ - Natural <-> Word#/BigNat#+ - Integer <-> Int#/Word#/Natural/BigNat# (+ Int64#/Word64# on 32-bit arch)++For example, we have the following primitives:+ - integerToWord# :: Integer -> Word#+ - integerFromWord# :: Word# -> Integer+ - integerToInt# :: Integer -> Int#+ - ...++Compared to optimising `fromIntegral :: (Integral a, Num b) => a -> b` where `a`+and `b` are arbitrary, we only have to write rewrite rules for the concrete+types that can be converted from and to Natural/Integer. All the other ones+necessarily pass through these concrete types!++For example we have the following rules:+ integerToWord# (integerFromWord# x) ===> x+ integerToInt# (integerFromWord# x) ===> word2Int# x++But we don't need rules to handle conversion from/to e.g. Word32# because there+is no Word32#-to-Integer primitive: Word32# must be converted into something+else first (e.g. Word#) for which we have rules.++We rely on inlining of fromInteger/toInteger and on other transformations (e.g.+float-in) to make these rules likely to fire. It seems to work well in practice.++Example 1: converting an Int into a Word++ fromIntegral @Int @Word x++ ===> {inline fromIntegral}+ fromInteger @Word (toInteger @Int x)++ ===> {inline fromInteger and toInteger}+ W# (integerToWord# (case x of { I# x# -> IS x# }))++ ===> {float-in}+ case x of { I# x# -> W# (integerToWord# (IS x#)) }++ ===> {rewrite rule for "integerToWord# . IS"}+ case x of { I# x# -> W# (int2Word# x#) }+++Example 2: converting an Int8 into a Word32++ fromIntegral @Int8 @Word32 x++ ===> {inline fromIntegral}+ fromInteger @Word32 (toInteger @Int8 x)++ ===> {inline fromInteger and toInteger}+ W32# (wordToWord32# (integerToWord# (case x of { I8# x# -> IS (int8ToInt# x#) })))++ ===> {float-in}+ case x of { I8# x# -> W32# (wordToWord32# (integerToWord# (IS (int8ToInt# x#)))) }++ ===> {rewrite rule for "integerToWord# . IS"}+ case x of { I8# x# -> W32# (wordToWord32# (int2Word# (int8ToInt# x#))) }++ Notice that in the resulting expression the value passes through types Int#+ and Word# with native machine word size: it is first sign-extended from Int8#+ to Int#, then cast into Word#, and finally truncated into Word32#. These are+ all very cheap operations that are performed in registers without allocating+ anything in the heap.++++Historical fromIntegral optimisations+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++In the past, `fromIntegral` function in the Prelude was special because many+rewrite rules were mentioning it explicitly. For example to replace a call to+`fromIntegral :: Int -> Word`, which allocates an intermediate Integer, with a+call to `intToWord`, which is a no-op when compiled into machine code. Nowadays+`fromIntegral` isn't a special function anymore and we just INLINE it (see above).++- first `fromIntegral` was specialized (SPECIALIZE pragma). However it would+need N^2 pragmas to cover every case and it wouldn't cover user defined numeric+types which don't belong to base.++- `-fwarn-identities` enables a warning to detect useless conversions via+fromIntegral (since 0656c72a8f):++ > fromIntegral (1 :: Int) :: Int++ <interactive>:3:21: warning: [-Widentities]+ Call of fromIntegral :: Int -> Int+ can probably be omitted+++- many rules were added (e.g. in e0c787c10f) to perform float-in transformations+explicitly (to allow more fromIntegral rules to fire) and to replace some+fromIntegral calls with faster operations:++ "fromIntegral/Int8->Int8" fromIntegral = id :: Int8 -> Int8+ "fromIntegral/a->Int8" fromIntegral = \x -> case fromIntegral x of I# x# -> I8# (intToInt8# x#)+ "fromIntegral/Int8->a" fromIntegral = \(I8# x#) -> fromIntegral (I# x#)++It worked but there were still some issues with this approach:++1. These rules only work for `fromIntegral`. If we wanted to define our own+ similar function (e.g. using other type-classes), we would also have to redefine+ all the rules to get similar performance.++2. `fromIntegral` had to be marked `NOINLINE [1]`:+ - NOINLINE to allow rules to match+ - [1] to allow inlining in later phases to avoid incurring a function call+ overhead for such a trivial operation++ Users of the function had to be careful because a simple helper without an+ INLINE pragma like:++ toInt :: Integral a => a -> Int+ toInt = fromIntegral++ had the following unfolding:++ toInt = integerToInt . toInteger++ which doesn't mention `fromIntegral` anymore. Hence `fromIntegral` rules+ wouldn't fire for codes using `toInt` while they would if they had used+ `fromIntegral` directly!+ For this reason, a bunch of rules for bignum primitives as we have now were+ already present to handle these cases.++3. These rewrite rules were tedious to write and error-prone (cf #19345).++For these reasons, it is simpler to not consider fromIntegral special at all and+to only rely on rewrite rules for bignum functions.++-}++-- See Note [Optimising conversions between numeric types]+{-# RULES+"Word# -> Natural -> Integer"+ forall x. integerFromNatural (NS x) = integerFromWord# x++"BigNat# -> Natural -> Integer"+ forall x. integerFromNatural (NB x) = IP x++"Int# -> Integer -> Int#"+ forall x. integerToInt# (IS x) = x++"Word# -> Integer -> Word#"+ forall x. integerToWord# (integerFromWord# x) = x++"Natural -> Integer -> Natural (wrap)"+ forall x. integerToNatural (integerFromNatural x) = x++"Natural -> Integer -> Natural (throw)"+ forall x. integerToNaturalThrow (integerFromNatural x) = x++"Natural -> Integer -> Natural (clamp)"+ forall x. integerToNaturalClamp (integerFromNatural x) = x++"Natural -> Integer -> Word#"+ forall x. integerToWord# (integerFromNatural x) = naturalToWord# x++"Int# -> Integer -> Word#"+ forall x. integerToWord# (IS x) = int2Word# x++"Word# -> Integer -> Int#"+ forall x. integerToInt# (integerFromWord# x) = word2Int# x++"Word# -> Integer -> Natural (wrap)"+ forall x. integerToNatural (integerFromWord# x) = NS x++"Word# -> Integer -> Natural (throw)"+ forall x. integerToNaturalThrow (integerFromWord# x) = NS x++"Word# -> Integer -> Natural (clamp)"+ forall x. integerToNaturalClamp (integerFromWord# x) = NS x++#-}++{-# RULES++"Int64# -> Integer -> Int64#"+ forall x. integerToInt64# (integerFromInt64# x) = x++"Word64# -> Integer -> Word64#"+ forall x. integerToWord64# (integerFromWord64# x) = x++"Int64# -> Integer -> Word64#"+ forall x. integerToWord64# (integerFromInt64# x) = int64ToWord64# x++"Word64# -> Integer -> Int64#"+ forall x. integerToInt64# (integerFromWord64# x) = word64ToInt64# x++"Word# -> Integer -> Word64#"+ forall x. integerToWord64# (integerFromWord# x) = wordToWord64# x++"Word64# -> Integer -> Word#"+ forall x. integerToWord# (integerFromWord64# x) = word64ToWord# x++"Int# -> Integer -> Int64#"+ forall x. integerToInt64# (IS x) = intToInt64# x++"Int64# -> Integer -> Int#"+ forall x. integerToInt# (integerFromInt64# x) = int64ToInt# x++"Int# -> Integer -> Word64#"+ forall x. integerToWord64# (IS x) = int64ToWord64# (intToInt64# x)++"Int64# -> Integer -> Word#"+ forall x. integerToWord# (integerFromInt64# x) = int2Word# (int64ToInt# x)++"Word# -> Integer -> Int64#"+ forall x. integerToInt64# (integerFromWord# x) = word64ToInt64# (wordToWord64# x)++"Word64# -> Integer -> Int#"+ forall x. integerToInt# (integerFromWord64# x) = word2Int# (word64ToWord# x)++#-}
src/GHC/Num/Natural.hs view
@@ -72,6 +72,7 @@ -- | Create a Natural from a BigNat# (respect the invariants) naturalFromBigNat# :: BigNat# -> Natural+{-# NOINLINE naturalFromBigNat# #-} naturalFromBigNat# x = case bigNatSize# x of 0# -> naturalZero 1# -> NS (bigNatIndex# x 0#)@@ -79,6 +80,7 @@ -- | Convert a Natural into a BigNat# naturalToBigNat# :: Natural -> BigNat#+{-# NOINLINE naturalToBigNat# #-} naturalToBigNat# (NS w) = bigNatFromWord# w naturalToBigNat# (NB bn) = bn @@ -112,7 +114,6 @@ -- | Convert a Natural into a Word# clamping to (maxBound :: Word#). naturalToWordClamp# :: Natural -> Word#-{-# NOINLINE naturalToWordClamp #-} naturalToWordClamp# (NS x) = x naturalToWordClamp# (NB _) = WORD_MAXBOUND## @@ -140,7 +141,6 @@ -- | Equality test for Natural naturalEq# :: Natural -> Natural -> Bool#-{-# NOINLINE naturalEq# #-} naturalEq# (NS x) (NS y) = x `eqWord#` y naturalEq# (NB x) (NB y) = bigNatEq# x y naturalEq# _ _ = 0#@@ -151,7 +151,6 @@ -- | Inequality test for Natural naturalNe# :: Natural -> Natural -> Bool#-{-# NOINLINE naturalNe# #-} naturalNe# (NS x) (NS y) = x `neWord#` y naturalNe# (NB x) (NB y) = bigNatNe# x y naturalNe# _ _ = 1#@@ -162,7 +161,6 @@ -- | Greater or equal test for Natural naturalGe# :: Natural -> Natural -> Bool#-{-# NOINLINE naturalGe# #-} naturalGe# (NS x) (NS y) = x `geWord#` y naturalGe# (NS _) (NB _) = 0# naturalGe# (NB _) (NS _) = 1#@@ -174,7 +172,6 @@ -- | Lower or equal test for Natural naturalLe# :: Natural -> Natural -> Bool#-{-# NOINLINE naturalLe# #-} naturalLe# (NS x) (NS y) = x `leWord#` y naturalLe# (NS _) (NB _) = 1# naturalLe# (NB _) (NS _) = 0#@@ -187,7 +184,6 @@ -- | Greater test for Natural naturalGt# :: Natural -> Natural -> Bool#-{-# NOINLINE naturalGt# #-} naturalGt# (NS x) (NS y) = x `gtWord#` y naturalGt# (NS _) (NB _) = 0# naturalGt# (NB _) (NS _) = 1#@@ -199,7 +195,6 @@ -- | Lower test for Natural naturalLt# :: Natural -> Natural -> Bool#-{-# NOINLINE naturalLt# #-} naturalLt# (NS x) (NS y) = x `ltWord#` y naturalLt# (NS _) (NB _) = 1# naturalLt# (NB _) (NS _) = 0#@@ -211,7 +206,6 @@ -- | Compare two Natural naturalCompare :: Natural -> Natural -> Ordering-{-# NOINLINE naturalCompare #-} naturalCompare (NS x) (NS y) = cmpW# x y naturalCompare (NB x) (NB y) = bigNatCompare x y naturalCompare (NS _) (NB _) = LT@@ -330,13 +324,11 @@ -- | Signum for Natural naturalSignum :: Natural -> Natural-{-# NOINLINE naturalSignum #-} naturalSignum (NS 0##) = NS 0## naturalSignum _ = NS 1## -- | Negate for Natural naturalNegate :: Natural -> Natural-{-# NOINLINE naturalNegate #-} naturalNegate (NS 0##) = NS 0## naturalNegate _ = raiseUnderflow @@ -429,6 +421,39 @@ naturalBit :: Word -> Natural naturalBit (W# i) = naturalBit# i +-- | @since 1.3+naturalSetBit# :: Natural -> Word# -> Natural+naturalSetBit# (NS n) i+ | isTrue# (i `ltWord#` WORD_SIZE_IN_BITS##) = NS (n `or#` (1## `uncheckedShiftL#` word2Int# i))+ | True = NB (bigNatSetBit# (bigNatFromWord# n) i)+naturalSetBit# (NB n) i = NB (bigNatSetBit# n i)++-- | @since 1.3+naturalSetBit :: Natural -> Word -> Natural+naturalSetBit !n (W# i) = naturalSetBit# n i++-- | @since 1.3+naturalClearBit# :: Natural -> Word# -> Natural+naturalClearBit# x@(NS n) i+ | isTrue# (i `ltWord#` WORD_SIZE_IN_BITS##) = NS (n `and#` not# (1## `uncheckedShiftL#` word2Int# i))+ | True = x+naturalClearBit# (NB n) i = naturalFromBigNat# (bigNatClearBit# n i)++-- | @since 1.3+naturalClearBit :: Natural -> Word -> Natural+naturalClearBit !n (W# i) = naturalClearBit# n i++-- | @since 1.3+naturalComplementBit# :: Natural -> Word# -> Natural+naturalComplementBit# (NS n) i+ | isTrue# (i `ltWord#` WORD_SIZE_IN_BITS##) = NS (n `xor#` (1## `uncheckedShiftL#` word2Int# i))+ | True = NB (bigNatSetBit# (bigNatFromWord# n) i)+naturalComplementBit# (NB n) i = naturalFromBigNat# (bigNatComplementBit# n i)++-- | @since 1.3+naturalComplementBit :: Natural -> Word -> Natural+naturalComplementBit !n (W# i) = naturalComplementBit# n i+ -- | Compute greatest common divisor. naturalGcd :: Natural -> Natural -> Natural {-# NOINLINE naturalGcd #-}@@ -518,7 +543,6 @@ -- byte first (big-endian) if @1#@ or least significant byte first -- (little-endian) if @0#@. naturalToAddr# :: Natural -> Addr# -> Bool# -> State# s -> (# State# s, Word# #)-{-# NOINLINE naturalToAddr# #-} naturalToAddr# (NS i) = wordToAddr# i naturalToAddr# (NB n) = bigNatToAddr# n @@ -543,7 +567,6 @@ -- -- Null higher limbs are automatically trimed. naturalFromAddr# :: Word# -> Addr# -> Bool# -> State# s -> (# State# s, Natural #)-{-# NOINLINE naturalFromAddr# #-} naturalFromAddr# sz addr e s = case bigNatFromAddr# sz addr e s of (# s', n #) -> (# s', naturalFromBigNat# n #)@@ -568,7 +591,6 @@ -- byte first (big-endian) if @1#@ or least significant byte first -- (little-endian) if @0#@. naturalToMutableByteArray# :: Natural -> MutableByteArray# s -> Word# -> Bool# -> State# s -> (# State# s, Word# #)-{-# NOINLINE naturalToMutableByteArray# #-} naturalToMutableByteArray# (NS w) = wordToMutableByteArray# w naturalToMutableByteArray# (NB a) = bigNatToMutableByteArray# a @@ -582,6 +604,17 @@ -- -- Null higher limbs are automatically trimed. naturalFromByteArray# :: Word# -> ByteArray# -> Word# -> Bool# -> State# s -> (# State# s, Natural #)-{-# NOINLINE naturalFromByteArray# #-} naturalFromByteArray# sz ba off e s = case bigNatFromByteArray# sz ba off e s of (# s', a #) -> (# s', naturalFromBigNat# a #)++++-- See Note [Optimising conversions between numeric types]+-- in GHC.Num.Integer+{-# RULES+"Word# -> Natural -> Word#"+ forall x. naturalToWord# (NS x) = x++"BigNat# -> Natural -> BigNat#"+ forall x. naturalToBigNat# (naturalFromBigNat# x) = x+#-}
src/GHC/Num/Primitives.hs view
@@ -598,7 +598,6 @@ -- Note [ghc-bignum exceptions] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- -- `ghc-bignum` package can't depend on `base` package (it would create a cyclic -- dependency). Hence it can't import "Control.Exception" and throw exceptions -- the usual way. Instead it uses some wired-in functions from `ghc-prim` which
src/GHC/Num/WordArray.hs view
@@ -79,17 +79,17 @@ -- | Create a new WordArray# of the given size (*in Word#*), apply the action to -- it, trim its most significant zeroes, then return it frozen-withNewWordArrayTrimed#+withNewWordArrayTrimmed# :: Int# -- ^ Size in Word -> (MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld) -> WordArray#-withNewWordArrayTrimed# sz act = withNewWordArray# sz \mwa s ->+withNewWordArrayTrimmed# sz act = withNewWordArray# sz \mwa s -> case act mwa s of s' -> mwaTrimZeroes# mwa s' -- | Create two new WordArray# of the given sizes (*in Word#*), apply the action -- to them, trim their most significant zeroes, then return them frozen-withNewWordArray2Trimed#+withNewWordArray2Trimmed# :: Int# -- ^ Size in Word -> Int# -- ^ Ditto -> (MutableWordArray# RealWorld@@ -97,7 +97,7 @@ -> State# RealWorld -> State# RealWorld) -> (# WordArray#, WordArray# #)-withNewWordArray2Trimed# sz1 sz2 act = withNewWordArray2# sz1 sz2 \mwa1 mwa2 s ->+withNewWordArray2Trimmed# sz1 sz2 act = withNewWordArray2# sz1 sz2 \mwa1 mwa2 s -> case act mwa1 mwa2 s of s' -> case mwaTrimZeroes# mwa1 s' of s'' -> mwaTrimZeroes# mwa2 s''@@ -105,11 +105,11 @@ -- | Create a new WordArray# of the given size (*in Word#*), apply the action to -- it. If the action returns true#, trim its most significant zeroes, then -- return it frozen. Otherwise, return ().-withNewWordArrayTrimedMaybe#+withNewWordArrayTrimmedMaybe# :: Int# -- ^ Size in Word -> (MutableWordArray# RealWorld -> State# RealWorld -> (# State# RealWorld, Bool# #)) -> (# (# #) | WordArray# #)-withNewWordArrayTrimedMaybe# sz act = case runRW# io of (# _, a #) -> a+withNewWordArrayTrimmedMaybe# sz act = case runRW# io of (# _, a #) -> a where io s = case newWordArray# sz s of