summaryrefslogtreecommitdiff
path: root/libraries/base/GHC/Natural.hs
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/base/GHC/Natural.hs')
-rw-r--r--libraries/base/GHC/Natural.hs682
1 files changed, 123 insertions, 559 deletions
diff --git a/libraries/base/GHC/Natural.hs b/libraries/base/GHC/Natural.hs
index 5912f75e29..4d5a935e7c 100644
--- a/libraries/base/GHC/Natural.hs
+++ b/libraries/base/GHC/Natural.hs
@@ -1,155 +1,82 @@
+{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
-{-# LANGUAGE UnboxedTuples #-}
-
------------------------------------------------------------------------------
--- |
--- Module : GHC.Natural
--- Copyright : (C) 2014 Herbert Valerio Riedel,
--- (C) 2011 Edward Kmett
--- License : see libraries/base/LICENSE
---
--- Maintainer : libraries@haskell.org
--- Stability : internal
--- Portability : non-portable (GHC Extensions)
---
--- The arbitrary-precision 'Natural' number type.
---
--- __Note__: This is an internal GHC module with an API subject to
--- change. It's recommended use the "Numeric.Natural" module to import
--- the 'Natural' type.
---
--- @since 4.8.0.0
------------------------------------------------------------------------------
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE ViewPatterns #-}
+{-# LANGUAGE UnboxedSums #-}
+
+{-# OPTIONS_HADDOCK not-home #-}
+
+-- | Compatibility module for pre ghc-bignum code.
module GHC.Natural
- ( -- * The 'Natural' number type
- --
- -- | __Warning__: The internal implementation of 'Natural'
- -- (i.e. which constructors are available) depends on the
- -- 'Integer' backend used!
- Natural(..)
- , mkNatural
- , isValidNatural
- -- * Arithmetic
- , plusNatural
- , minusNatural
- , minusNaturalMaybe
- , timesNatural
- , negateNatural
- , signumNatural
- , quotRemNatural
- , quotNatural
- , remNatural
- , gcdNatural
- , lcmNatural
- -- * Bits
- , andNatural
- , orNatural
- , xorNatural
- , bitNatural
- , testBitNatural
- , popCountNatural
- , shiftLNatural
- , shiftRNatural
- -- * Conversions
- , naturalToInteger
- , naturalToWord
- , naturalToInt
- , naturalFromInteger
- , wordToNatural
- , intToNatural
- , naturalToWordMaybe
- , wordToNatural#
- , wordToNaturalBase
- -- * Modular arithmetic
- , powModNatural
- ) where
-
-#include "MachDeps.h"
-
-import GHC.Classes
-import GHC.Maybe
-import GHC.Types
+ ( Natural (NatS#, NatJ#)
+ , BigNat (..)
+ , mkNatural
+ , isValidNatural
+ -- * Arithmetic
+ , plusNatural
+ , minusNatural
+ , minusNaturalMaybe
+ , timesNatural
+ , negateNatural
+ , signumNatural
+ , quotRemNatural
+ , quotNatural
+ , remNatural
+ , gcdNatural
+ , lcmNatural
+ -- * Bits
+ , andNatural
+ , orNatural
+ , xorNatural
+ , bitNatural
+ , testBitNatural
+ , popCountNatural
+ , shiftLNatural
+ , shiftRNatural
+ -- * Conversions
+ , naturalToInteger
+ , naturalToWord
+ , naturalToInt
+ , naturalFromInteger
+ , wordToNatural
+ , intToNatural
+ , naturalToWordMaybe
+ , wordToNatural#
+ -- * Modular arithmetic
+ , powModNatural
+ )
+where
+
import GHC.Prim
-import {-# SOURCE #-} GHC.Exception.Type (underflowException, divZeroException)
-#if defined(MIN_VERSION_integer_gmp)
-import GHC.Integer.GMP.Internals
-#else
-import GHC.Integer
-#endif
-
-default ()
-
--- Most high-level operations need to be marked `NOINLINE` as
--- otherwise GHC doesn't recognize them and fails to apply constant
--- folding to `Natural`-typed expression.
---
--- To this end, the CPP hack below allows to write the pseudo-pragma
---
--- {-# CONSTANT_FOLDED plusNatural #-}
---
--- which is simply expanded into a
---
--- {-# NOINLINE plusNatural #-}
---
---
--- TODO: Note that some functions have commented CONSTANT_FOLDED annotations,
--- that's because the Integer counter-parts of these functions do actually have
--- a builtinRule in PrelRules, where the Natural functions do not. The plan is
--- to eventually also add builtin rules for those functions on Natural.
-#define CONSTANT_FOLDED NOINLINE
+import GHC.Types
+import GHC.Maybe
+import GHC.Num.Natural (Natural)
+import GHC.Num.Integer (Integer)
+import qualified GHC.Num.Natural as N
+import qualified GHC.Num.Integer as I
--------------------------------------------------------------------------------
--- Arithmetic underflow
--------------------------------------------------------------------------------
+data BigNat = BN# { unBigNat :: ByteArray# }
--- We put them here because they are needed relatively early
--- in the libraries before the Exception type has been defined yet.
+{-# COMPLETE NatS#, NatJ# #-}
-{-# NOINLINE underflowError #-}
-underflowError :: a
-underflowError = raise# underflowException
+pattern NatS# :: Word# -> Natural
+pattern NatS# w = N.NS w
-{-# NOINLINE divZeroError #-}
-divZeroError :: a
-divZeroError = raise# divZeroException
+pattern NatJ# :: BigNat -> Natural
+pattern NatJ# b <- N.NB (BN# -> b)
+ where
+ NatJ# b = N.NB (unBigNat b)
--------------------------------------------------------------------------------
--- Natural type
--------------------------------------------------------------------------------
+int2Word :: Int -> Word
+int2Word (I# i) = W# (int2Word# i)
-#if defined(MIN_VERSION_integer_gmp)
--- TODO: if saturated arithmetic is to used, replace 'underflowError' by '0'
+word2Int :: Word -> Int
+word2Int (W# w) = I# (word2Int# w)
--- | Type representing arbitrary-precision non-negative integers.
---
--- >>> 2^100 :: Natural
--- 1267650600228229401496703205376
---
--- Operations whose result would be negative @'Control.Exception.throw'
--- ('Control.Exception.Underflow' :: 'Control.Exception.ArithException')@,
---
--- >>> -1 :: Natural
--- *** Exception: arithmetic underflow
---
--- @since 4.8.0.0
-data Natural = NatS# GmpLimb# -- ^ in @[0, maxBound::Word]@
- | NatJ# {-# UNPACK #-} !BigNat -- ^ in @]maxBound::Word, +inf[@
- --
- -- __Invariant__: 'NatJ#' is used
- -- /iff/ value doesn't fit in
- -- 'NatS#' constructor.
- -- NB: Order of constructors *must*
- -- coincide with 'Ord' relation
- deriving ( Eq -- ^ @since 4.8.0.0
- , Ord -- ^ @since 4.8.0.0
- )
-
-zero, one :: Natural
-zero = NatS# 0##
-one = NatS# 1##
+-- | Construct 'Natural' value from list of 'Word's.
+mkNatural :: [Word] -> Natural
+mkNatural = N.naturalFromWordList
-- | Test whether all internal invariants are satisfied by 'Natural' value
--
@@ -158,477 +85,114 @@ one = NatS# 1##
--
-- @since 4.8.0.0
isValidNatural :: Natural -> Bool
-isValidNatural (NatS# _) = True
-isValidNatural (NatJ# bn) = isTrue# (isValidBigNat# bn)
- -- A 1-limb BigNat could fit into a NatS#, so we
- -- require at least 2 limbs.
- && isTrue# (sizeofBigNat# bn ># 1#)
-
-signumNatural :: Natural -> Natural
-signumNatural (NatS# 0##) = zero
-signumNatural _ = one
--- {-# CONSTANT_FOLDED signumNatural #-}
-
-negateNatural :: Natural -> Natural
-negateNatural (NatS# 0##) = zero
-negateNatural _ = underflowError
--- {-# CONSTANT_FOLDED negateNatural #-}
-
--- | @since 4.10.0.0
-naturalFromInteger :: Integer -> Natural
-naturalFromInteger (S# i#)
- | isTrue# (i# >=# 0#) = NatS# (int2Word# i#)
-naturalFromInteger (Jp# bn) = bigNatToNatural bn
-naturalFromInteger _ = underflowError
-{-# CONSTANT_FOLDED naturalFromInteger #-}
-
--- | Compute greatest common divisor.
-gcdNatural :: Natural -> Natural -> Natural
-gcdNatural (NatS# 0##) y = y
-gcdNatural x (NatS# 0##) = x
-gcdNatural (NatS# 1##) _ = one
-gcdNatural _ (NatS# 1##) = one
-gcdNatural (NatJ# x) (NatJ# y) = bigNatToNatural (gcdBigNat x y)
-gcdNatural (NatJ# x) (NatS# y) = NatS# (gcdBigNatWord x y)
-gcdNatural (NatS# x) (NatJ# y) = NatS# (gcdBigNatWord y x)
-gcdNatural (NatS# x) (NatS# y) = NatS# (gcdWord x y)
-
--- | Compute least common multiple.
-lcmNatural :: Natural -> Natural -> Natural
--- Make sure we are strict in all arguments (#17499)
-lcmNatural (NatS# 0##) !_ = zero
-lcmNatural _ (NatS# 0##) = zero
-lcmNatural (NatS# 1##) y = y
-lcmNatural x (NatS# 1##) = x
-lcmNatural x y = (x `quotNatural` (gcdNatural x y)) `timesNatural` y
-
-----------------------------------------------------------------------------
-
-quotRemNatural :: Natural -> Natural -> (Natural, Natural)
--- Make sure we are strict in all arguments (#17499)
-quotRemNatural !_ (NatS# 0##) = divZeroError
-quotRemNatural n (NatS# 1##) = (n,zero)
-quotRemNatural n@(NatS# _) (NatJ# _) = (zero, n)
-quotRemNatural (NatS# n) (NatS# d) = case quotRemWord# n d of
- (# q, r #) -> (NatS# q, NatS# r)
-quotRemNatural (NatJ# n) (NatS# d) = case quotRemBigNatWord n d of
- (# q, r #) -> (bigNatToNatural q, NatS# r)
-quotRemNatural (NatJ# n) (NatJ# d) = case quotRemBigNat n d of
- (# q, r #) -> (bigNatToNatural q, bigNatToNatural r)
--- {-# CONSTANT_FOLDED quotRemNatural #-}
-
-quotNatural :: Natural -> Natural -> Natural
--- Make sure we are strict in all arguments (#17499)
-quotNatural !_ (NatS# 0##) = divZeroError
-quotNatural n (NatS# 1##) = n
-quotNatural (NatS# _) (NatJ# _) = zero
-quotNatural (NatS# n) (NatS# d) = NatS# (quotWord# n d)
-quotNatural (NatJ# n) (NatS# d) = bigNatToNatural (quotBigNatWord n d)
-quotNatural (NatJ# n) (NatJ# d) = bigNatToNatural (quotBigNat n d)
--- {-# CONSTANT_FOLDED quotNatural #-}
-
-remNatural :: Natural -> Natural -> Natural
--- Make sure we are strict in all arguments (#17499)
-remNatural !_ (NatS# 0##) = divZeroError
-remNatural _ (NatS# 1##) = zero
-remNatural n@(NatS# _) (NatJ# _) = n
-remNatural (NatS# n) (NatS# d) = NatS# (remWord# n d)
-remNatural (NatJ# n) (NatS# d) = NatS# (remBigNatWord n d)
-remNatural (NatJ# n) (NatJ# d) = bigNatToNatural (remBigNat n d)
--- {-# CONSTANT_FOLDED remNatural #-}
-
--- | @since 4.12.0.0
-naturalToInteger :: Natural -> Integer
-naturalToInteger (NatS# w) = wordToInteger w
-naturalToInteger (NatJ# bn) = Jp# bn
-{-# CONSTANT_FOLDED naturalToInteger #-}
-
-andNatural :: Natural -> Natural -> Natural
-andNatural (NatS# n) (NatS# m) = NatS# (n `and#` m)
-andNatural (NatS# n) (NatJ# m) = NatS# (n `and#` bigNatToWord m)
-andNatural (NatJ# n) (NatS# m) = NatS# (bigNatToWord n `and#` m)
-andNatural (NatJ# n) (NatJ# m) = bigNatToNatural (andBigNat n m)
--- {-# CONSTANT_FOLDED andNatural #-}
-
-orNatural :: Natural -> Natural -> Natural
-orNatural (NatS# n) (NatS# m) = NatS# (n `or#` m)
-orNatural (NatS# n) (NatJ# m) = NatJ# (orBigNat (wordToBigNat n) m)
-orNatural (NatJ# n) (NatS# m) = NatJ# (orBigNat n (wordToBigNat m))
-orNatural (NatJ# n) (NatJ# m) = NatJ# (orBigNat n m)
--- {-# CONSTANT_FOLDED orNatural #-}
-
-xorNatural :: Natural -> Natural -> Natural
-xorNatural (NatS# n) (NatS# m) = NatS# (n `xor#` m)
-xorNatural (NatS# n) (NatJ# m) = NatJ# (xorBigNat (wordToBigNat n) m)
-xorNatural (NatJ# n) (NatS# m) = NatJ# (xorBigNat n (wordToBigNat m))
-xorNatural (NatJ# n) (NatJ# m) = bigNatToNatural (xorBigNat n m)
--- {-# CONSTANT_FOLDED xorNatural #-}
-
-bitNatural :: Int# -> Natural
-bitNatural i#
- | isTrue# (i# <# WORD_SIZE_IN_BITS#) = NatS# (1## `uncheckedShiftL#` i#)
- | True = NatJ# (bitBigNat i#)
--- {-# CONSTANT_FOLDED bitNatural #-}
-
-testBitNatural :: Natural -> Int -> Bool
-testBitNatural (NatS# w) (I# i#)
- | isTrue# (i# <# WORD_SIZE_IN_BITS#) =
- isTrue# ((w `and#` (1## `uncheckedShiftL#` i#)) `neWord#` 0##)
- | True = False
-testBitNatural (NatJ# bn) (I# i#) = testBitBigNat bn i#
--- {-# CONSTANT_FOLDED testBitNatural #-}
-
-popCountNatural :: Natural -> Int
-popCountNatural (NatS# w) = I# (word2Int# (popCnt# w))
-popCountNatural (NatJ# bn) = I# (popCountBigNat bn)
--- {-# CONSTANT_FOLDED popCountNatural #-}
-
-shiftLNatural :: Natural -> Int -> Natural
-shiftLNatural n (I# 0#) = n
-shiftLNatural (NatS# 0##) _ = zero
-shiftLNatural (NatS# 1##) (I# i#) = bitNatural i#
-shiftLNatural (NatS# w) (I# i#)
- = bigNatToNatural (shiftLBigNat (wordToBigNat w) i#)
-shiftLNatural (NatJ# bn) (I# i#)
- = bigNatToNatural (shiftLBigNat bn i#)
--- {-# CONSTANT_FOLDED shiftLNatural #-}
-
-shiftRNatural :: Natural -> Int -> Natural
-shiftRNatural n (I# 0#) = n
-shiftRNatural (NatS# w) (I# i#)
- | isTrue# (i# >=# WORD_SIZE_IN_BITS#) = zero
- | True = NatS# (w `uncheckedShiftRL#` i#)
-shiftRNatural (NatJ# bn) (I# i#) = bigNatToNatural (shiftRBigNat bn i#)
--- {-# CONSTANT_FOLDED shiftRNatural #-}
-
-----------------------------------------------------------------------------
+isValidNatural = N.naturalCheck
-- | 'Natural' Addition
plusNatural :: Natural -> Natural -> Natural
-plusNatural (NatS# 0##) y = y
-plusNatural x (NatS# 0##) = x
-plusNatural (NatS# x) (NatS# y)
- = case plusWord2# x y of
- (# 0##, l #) -> NatS# l
- (# h, l #) -> NatJ# (wordToBigNat2 h l)
-plusNatural (NatS# x) (NatJ# y) = NatJ# (plusBigNatWord y x)
-plusNatural (NatJ# x) (NatS# y) = NatJ# (plusBigNatWord x y)
-plusNatural (NatJ# x) (NatJ# y) = NatJ# (plusBigNat x y)
-{-# CONSTANT_FOLDED plusNatural #-}
-
--- | 'Natural' multiplication
-timesNatural :: Natural -> Natural -> Natural
--- Make sure we are strict in all arguments (#17499)
-timesNatural !_ (NatS# 0##) = zero
-timesNatural (NatS# 0##) _ = zero
-timesNatural x (NatS# 1##) = x
-timesNatural (NatS# 1##) y = y
-timesNatural (NatS# x) (NatS# y) = case timesWord2# x y of
- (# 0##, 0## #) -> NatS# 0##
- (# 0##, xy #) -> NatS# xy
- (# h , l #) -> NatJ# (wordToBigNat2 h l)
-timesNatural (NatS# x) (NatJ# y) = NatJ# (timesBigNatWord y x)
-timesNatural (NatJ# x) (NatS# y) = NatJ# (timesBigNatWord x y)
-timesNatural (NatJ# x) (NatJ# y) = NatJ# (timesBigNat x y)
-{-# CONSTANT_FOLDED timesNatural #-}
+plusNatural = N.naturalAdd
-- | 'Natural' subtraction. May @'Control.Exception.throw'
-- 'Control.Exception.Underflow'@.
minusNatural :: Natural -> Natural -> Natural
-minusNatural x (NatS# 0##) = x
-minusNatural (NatS# x) (NatS# y) = case subWordC# x y of
- (# l, 0# #) -> NatS# l
- _ -> underflowError
-minusNatural (NatS# _) (NatJ# _) = underflowError
-minusNatural (NatJ# x) (NatS# y)
- = bigNatToNatural (minusBigNatWord x y)
-minusNatural (NatJ# x) (NatJ# y)
- = bigNatToNatural (minusBigNat x y)
-{-# CONSTANT_FOLDED minusNatural #-}
+minusNatural = N.naturalSubThrow
-- | 'Natural' subtraction. Returns 'Nothing's for non-positive results.
--
-- @since 4.8.0.0
minusNaturalMaybe :: Natural -> Natural -> Maybe Natural
--- Make sure we are strict in all arguments (#17499)
-minusNaturalMaybe !x (NatS# 0##) = Just x
-minusNaturalMaybe (NatS# x) (NatS# y) = case subWordC# x y of
- (# l, 0# #) -> Just (NatS# l)
- _ -> Nothing
-minusNaturalMaybe (NatS# _) (NatJ# _) = Nothing
-minusNaturalMaybe (NatJ# x) (NatS# y)
- = Just (bigNatToNatural (minusBigNatWord x y))
-minusNaturalMaybe (NatJ# x) (NatJ# y)
- | isTrue# (isNullBigNat# res) = Nothing
- | True = Just (bigNatToNatural res)
- where
- res = minusBigNat x y
-
--- | Convert 'BigNat' to 'Natural'.
--- Throws 'Control.Exception.Underflow' if passed a 'nullBigNat'.
-bigNatToNatural :: BigNat -> Natural
-bigNatToNatural bn
- | isTrue# (sizeofBigNat# bn ==# 1#) = NatS# (bigNatToWord bn)
- | isTrue# (isNullBigNat# bn) = underflowError
- | True = NatJ# bn
-
-naturalToBigNat :: Natural -> BigNat
-naturalToBigNat (NatS# w#) = wordToBigNat w#
-naturalToBigNat (NatJ# bn) = bn
-
-naturalToWord :: Natural -> Word
-naturalToWord (NatS# w#) = W# w#
-naturalToWord (NatJ# bn) = W# (bigNatToWord bn)
-
-naturalToInt :: Natural -> Int
-naturalToInt (NatS# w#) = I# (word2Int# w#)
-naturalToInt (NatJ# bn) = I# (bigNatToInt bn)
-
-----------------------------------------------------------------------------
-
--- | Convert a Word# into a Natural
---
--- Built-in rule ensures that applications of this function to literal Word# are
--- lifted into Natural literals.
-wordToNatural# :: Word# -> Natural
-wordToNatural# w# = NatS# w#
-{-# CONSTANT_FOLDED wordToNatural# #-}
-
--- | Convert a Word# into a Natural
---
--- In base we can't use wordToNatural# as built-in rules transform some of them
--- into Natural literals. Use this function instead.
-wordToNaturalBase :: Word# -> Natural
-wordToNaturalBase w# = NatS# w#
-
-#else /* !defined(MIN_VERSION_integer_gmp) */
-----------------------------------------------------------------------------
--- Use wrapped 'Integer' as fallback; taken from Edward Kmett's nats package
-
--- | Type representing arbitrary-precision non-negative integers.
---
--- Operations whose result would be negative @'Control.Exception.throw'
--- ('Control.Exception.Underflow' :: 'Control.Exception.ArithException')@.
---
--- @since 4.8.0.0
-newtype Natural = Natural Integer -- ^ __Invariant__: non-negative 'Integer'
- deriving (Eq,Ord)
+minusNaturalMaybe x y = case N.naturalSub x y of
+ (# () | #) -> Nothing
+ (# | n #) -> Just n
+-- | 'Natural' multiplication
+timesNatural :: Natural -> Natural -> Natural
+timesNatural = N.naturalMul
--- | Test whether all internal invariants are satisfied by 'Natural' value
---
--- This operation is mostly useful for test-suites and/or code which
--- constructs 'Natural' values directly.
---
--- @since 4.8.0.0
-isValidNatural :: Natural -> Bool
-isValidNatural (Natural i) = i >= wordToInteger 0##
+negateNatural :: Natural -> Natural
+negateNatural = N.naturalNegate
--- | Convert a 'Word#' into a 'Natural'
---
--- Built-in rule ensures that applications of this function to literal 'Word#'
--- are lifted into 'Natural' literals.
-wordToNatural# :: Word# -> Natural
-wordToNatural# w## = Natural (wordToInteger w##)
-{-# CONSTANT_FOLDED wordToNatural# #-}
+signumNatural :: Natural -> Natural
+signumNatural = N.naturalSignum
--- | Convert a 'Word#' into a Natural
---
--- In base we can't use wordToNatural# as built-in rules transform some of them
--- into Natural literals. Use this function instead.
-wordToNaturalBase :: Word# -> Natural
-wordToNaturalBase w## = Natural (wordToInteger w##)
+quotRemNatural :: Natural -> Natural -> (Natural, Natural)
+quotRemNatural = N.naturalQuotRem
--- | @since 4.10.0.0
-naturalFromInteger :: Integer -> Natural
-naturalFromInteger n
- | n >= wordToInteger 0## = Natural n
- | True = underflowError
-{-# INLINE naturalFromInteger #-}
+remNatural :: Natural -> Natural -> Natural
+remNatural = N.naturalRem
+quotNatural :: Natural -> Natural -> Natural
+quotNatural = N.naturalQuot
-- | Compute greatest common divisor.
gcdNatural :: Natural -> Natural -> Natural
-gcdNatural (Natural n) (Natural m) = Natural (n `gcdInteger` m)
+gcdNatural = N.naturalGcd
--- | Compute lowest common multiple.
+-- | Compute least common multiple.
lcmNatural :: Natural -> Natural -> Natural
-lcmNatural (Natural n) (Natural m) = Natural (n `lcmInteger` m)
-
--- | 'Natural' subtraction. Returns 'Nothing's for non-positive results.
---
--- @since 4.8.0.0
-minusNaturalMaybe :: Natural -> Natural -> Maybe Natural
-minusNaturalMaybe (Natural x) (Natural y)
- | x >= y = Just (Natural (x `minusInteger` y))
- | True = Nothing
-
-shiftLNatural :: Natural -> Int -> Natural
-shiftLNatural (Natural n) (I# i) = Natural (n `shiftLInteger` i)
--- {-# CONSTANT_FOLDED shiftLNatural #-}
-
-shiftRNatural :: Natural -> Int -> Natural
-shiftRNatural (Natural n) (I# i) = Natural (n `shiftRInteger` i)
--- {-# CONSTANT_FOLDED shiftRNatural #-}
-
-plusNatural :: Natural -> Natural -> Natural
-plusNatural (Natural x) (Natural y) = Natural (x `plusInteger` y)
-{-# CONSTANT_FOLDED plusNatural #-}
-
-minusNatural :: Natural -> Natural -> Natural
-minusNatural (Natural x) (Natural y)
- = if z `ltInteger` wordToInteger 0## then underflowError else Natural z
- where z = x `minusInteger` y
-{-# CONSTANT_FOLDED minusNatural #-}
+lcmNatural = N.naturalLcm
-timesNatural :: Natural -> Natural -> Natural
-timesNatural (Natural x) (Natural y) = Natural (x `timesInteger` y)
-{-# CONSTANT_FOLDED timesNatural #-}
+andNatural :: Natural -> Natural -> Natural
+andNatural = N.naturalAnd
orNatural :: Natural -> Natural -> Natural
-orNatural (Natural x) (Natural y) = Natural (x `orInteger` y)
--- {-# CONSTANT_FOLDED orNatural #-}
+orNatural = N.naturalOr
xorNatural :: Natural -> Natural -> Natural
-xorNatural (Natural x) (Natural y) = Natural (x `xorInteger` y)
--- {-# CONSTANT_FOLDED xorNatural #-}
-
-andNatural :: Natural -> Natural -> Natural
-andNatural (Natural x) (Natural y) = Natural (x `andInteger` y)
--- {-# CONSTANT_FOLDED andNatural #-}
-
-naturalToInt :: Natural -> Int
-naturalToInt (Natural i) = I# (integerToInt i)
+xorNatural = N.naturalXor
-naturalToWord :: Natural -> Word
-naturalToWord (Natural i) = W# (integerToWord i)
-
-naturalToInteger :: Natural -> Integer
-naturalToInteger (Natural i) = i
-{-# CONSTANT_FOLDED naturalToInteger #-}
+bitNatural :: Int# -> Natural
+bitNatural i = N.naturalBit# (int2Word# i)
testBitNatural :: Natural -> Int -> Bool
-testBitNatural (Natural n) (I# i) = testBitInteger n i
--- {-# CONSTANT_FOLDED testBitNatural #-}
+testBitNatural n i = N.naturalTestBit n (int2Word i)
popCountNatural :: Natural -> Int
-popCountNatural (Natural n) = I# (popCountInteger n)
+popCountNatural n = word2Int (N.naturalPopCount n)
-bitNatural :: Int# -> Natural
-bitNatural i#
- | isTrue# (i# <# WORD_SIZE_IN_BITS#) = wordToNaturalBase (1## `uncheckedShiftL#` i#)
- | True = Natural (1 `shiftLInteger` i#)
--- {-# CONSTANT_FOLDED bitNatural #-}
-
-quotNatural :: Natural -> Natural -> Natural
-quotNatural n@(Natural x) (Natural y)
- | y == wordToInteger 0## = divZeroError
- | y == wordToInteger 1## = n
- | True = Natural (x `quotInteger` y)
--- {-# CONSTANT_FOLDED quotNatural #-}
+shiftLNatural :: Natural -> Int -> Natural
+shiftLNatural n i = N.naturalShiftL n (int2Word i)
-remNatural :: Natural -> Natural -> Natural
-remNatural (Natural x) (Natural y)
- | y == wordToInteger 0## = divZeroError
- | y == wordToInteger 1## = wordToNaturalBase 0##
- | True = Natural (x `remInteger` y)
--- {-# CONSTANT_FOLDED remNatural #-}
+shiftRNatural :: Natural -> Int -> Natural
+shiftRNatural n i = N.naturalShiftR n (int2Word i)
-quotRemNatural :: Natural -> Natural -> (Natural, Natural)
-quotRemNatural n@(Natural x) (Natural y)
- | y == wordToInteger 0## = divZeroError
- | y == wordToInteger 1## = (n,wordToNaturalBase 0##)
- | True = case quotRemInteger x y of
- (# k, r #) -> (Natural k, Natural r)
--- {-# CONSTANT_FOLDED quotRemNatural #-}
+-- | @since 4.12.0.0
+naturalToInteger :: Natural -> Integer
+naturalToInteger = I.integerFromNatural
-signumNatural :: Natural -> Natural
-signumNatural (Natural x)
- | x == wordToInteger 0## = wordToNaturalBase 0##
- | True = wordToNaturalBase 1##
--- {-# CONSTANT_FOLDED signumNatural #-}
+naturalToWord :: Natural -> Word
+naturalToWord = N.naturalToWord
-negateNatural :: Natural -> Natural
-negateNatural (Natural x)
- | x == wordToInteger 0## = wordToNaturalBase 0##
- | True = underflowError
--- {-# CONSTANT_FOLDED negateNatural #-}
+naturalToInt :: Natural -> Int
+naturalToInt = N.naturalToInt
-#endif
+-- | @since 4.10.0.0
+naturalFromInteger :: Integer -> Natural
+naturalFromInteger = I.integerToNatural
-- | Construct 'Natural' from 'Word' value.
--
-- @since 4.8.0.0
wordToNatural :: Word -> Natural
-wordToNatural (W# w#) = wordToNatural# w#
+wordToNatural = N.naturalFromWord
+
+intToNatural :: Int -> Natural
+intToNatural = N.naturalFromIntThrow
-- | Try downcasting 'Natural' to 'Word' value.
-- Returns 'Nothing' if value doesn't fit in 'Word'.
--
-- @since 4.8.0.0
naturalToWordMaybe :: Natural -> Maybe Word
-#if defined(MIN_VERSION_integer_gmp)
-naturalToWordMaybe (NatS# w#) = Just (W# w#)
-naturalToWordMaybe (NatJ# _) = Nothing
-#else
-naturalToWordMaybe (Natural i)
- | i < maxw = Just (W# (integerToWord i))
- | True = Nothing
- where
- maxw = 1 `shiftLInteger` WORD_SIZE_IN_BITS#
-#endif
+naturalToWordMaybe n = case N.naturalToWordMaybe# n of
+ (# w | #) -> Just (W# w)
+ (# | () #) -> Nothing
+
+wordToNatural# :: Word -> Natural
+wordToNatural# = N.naturalFromWord
-- | \"@'powModNatural' /b/ /e/ /m/@\" computes base @/b/@ raised to
-- exponent @/e/@ modulo @/m/@.
--
-- @since 4.8.0.0
powModNatural :: Natural -> Natural -> Natural -> Natural
-#if defined(MIN_VERSION_integer_gmp)
--- Make sure we are strict in all arguments (#17499)
-powModNatural !_ !_ (NatS# 0##) = divZeroError
-powModNatural _ _ (NatS# 1##) = zero
-powModNatural _ (NatS# 0##) _ = one
-powModNatural (NatS# 0##) _ _ = zero
-powModNatural (NatS# 1##) _ _ = one
-powModNatural (NatS# b) (NatS# e) (NatS# m) = NatS# (powModWord b e m)
-powModNatural b e (NatS# m)
- = NatS# (powModBigNatWord (naturalToBigNat b) (naturalToBigNat e) m)
-powModNatural b e (NatJ# m)
- = bigNatToNatural (powModBigNat (naturalToBigNat b) (naturalToBigNat e) m)
-#else
--- Portable reference fallback implementation
-powModNatural (Natural b0) (Natural e0) (Natural m)
- | m == wordToInteger 0## = divZeroError
- | m == wordToInteger 1## = wordToNaturalBase 0##
- | e0 == wordToInteger 0## = wordToNaturalBase 1##
- | b0 == wordToInteger 0## = wordToNaturalBase 0##
- | b0 == wordToInteger 1## = wordToNaturalBase 1##
- | True = go b0 e0 (wordToInteger 1##)
- where
- go !b e !r
- | e `testBitInteger` 0# = go b' e' ((r `timesInteger` b) `modInteger` m)
- | e == wordToInteger 0## = naturalFromInteger r
- | True = go b' e' r
- where
- b' = (b `timesInteger` b) `modInteger` m
- e' = e `shiftRInteger` 1# -- slightly faster than "e `div` 2"
-#endif
-
-
--- | Construct 'Natural' value from list of 'Word's.
---
--- This function is used by GHC for constructing 'Natural' literals.
-mkNatural :: [Word] -- ^ value expressed in 32 bit chunks, least
- -- significant first
- -> Natural
-mkNatural [] = wordToNaturalBase 0##
-mkNatural (W# i : is') = wordToNaturalBase (i `and#` 0xffffffff##) `orNatural`
- shiftLNatural (mkNatural is') 32
-{-# CONSTANT_FOLDED mkNatural #-}
-
--- | Convert 'Int' to 'Natural'.
--- Throws 'Control.Exception.Underflow' when passed a negative 'Int'.
-intToNatural :: Int -> Natural
-intToNatural (I# i#)
- | isTrue# (i# <# 0#) = underflowError
- | True = wordToNaturalBase (int2Word# i#)
+powModNatural = N.naturalPowMod