packages feed

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