content: {-# LANGUAGE Trustworthy #-}
  {-# LANGUAGE NoImplicitPrelude #-}
  {-# LANGUAGE MagicHash #-}
  {-# LANGUAGE PatternSynonyms #-}
  {-# LANGUAGE ViewPatterns #-}
  {-# LANGUAGE UnboxedSums #-}
  
  {-# OPTIONS_HADDOCK not-home #-}
  
  -- | Compatibility module for pre ghc-bignum code.
  module GHC.Internal.Natural
     ( Natural (NatS#, NatJ#)
     , B.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
     , naturalToWordMaybe
     , wordToNatural
     , wordToNatural#
     , naturalFromInteger
       -- * Modular arithmetic
     , powModNatural
     )
  where
  
  import GHC.Internal.Prim
  import GHC.Internal.Types
  import GHC.Internal.Maybe
  import GHC.Internal.Bignum.Natural (Natural)
  import GHC.Internal.Bignum.Integer (Integer)
  import qualified GHC.Internal.Bignum.BigNat  as B
  import qualified GHC.Internal.Bignum.Natural as N
  import qualified GHC.Internal.Bignum.Integer as I
  
  {-# COMPLETE NatS#, NatJ# #-}
  
  pattern NatS# :: Word# -> Natural
  pattern NatS# w = N.NS w
  
  pattern NatJ# :: B.BigNat -> Natural
  pattern NatJ# b <- N.NB (B.BN# -> b)
     where
        NatJ# b = N.NB (B.unBigNat b)
  
  int2Word :: Int -> Word
  int2Word (I# i) = W# (int2Word# i)
  
  word2Int :: Word -> Int
  word2Int (W# w) = I# (word2Int# w)
  
  -- | Construct 'Natural' value from list of 'Word's.
  mkNatural :: [Word] -> Natural
  mkNatural = N.naturalFromWordList
  
  -- | Test whether all internal invariants are satisfied by 'Natural' value
  --
  -- This operation is mostly useful for test-suites and/or code which
  -- constructs 'Integer' values directly.
  --
  -- @since base-4.8.0.0
  isValidNatural :: Natural -> Bool
  isValidNatural = N.naturalCheck
  
  -- | 'Natural' Addition
  plusNatural :: Natural -> Natural -> Natural
  plusNatural = N.naturalAdd
  
  -- | 'Natural' subtraction. May @'GHC.Internal.Control.Exception.throw'
  -- 'Control.Exception.Underflow'@.
  minusNatural :: Natural -> Natural -> Natural
  minusNatural = N.naturalSubThrow
  
  -- | 'Natural' subtraction. Returns 'Nothing's for non-positive results.
  --
  -- @since base-4.8.0.0
  minusNaturalMaybe :: Natural -> Natural -> Maybe Natural
  minusNaturalMaybe x y = case N.naturalSub x y of
     (# (# #) |   #) -> Nothing
     (#       | n #) -> Just n
  
  -- | 'Natural' multiplication
  timesNatural :: Natural -> Natural -> Natural
  timesNatural = N.naturalMul
  
  negateNatural :: Natural -> Natural
  negateNatural = N.naturalNegate
  
  signumNatural :: Natural -> Natural
  signumNatural = N.naturalSignum
  
  quotRemNatural :: Natural -> Natural -> (Natural, Natural)
  quotRemNatural = N.naturalQuotRem
  
  remNatural :: Natural -> Natural -> Natural
  remNatural = N.naturalRem
  
  quotNatural :: Natural -> Natural -> Natural
  quotNatural = N.naturalQuot
  
  -- | Compute greatest common divisor.
  gcdNatural :: Natural -> Natural -> Natural
  gcdNatural = N.naturalGcd
  
  -- | Compute least common multiple.
  lcmNatural :: Natural -> Natural -> Natural
  lcmNatural = N.naturalLcm
  
  andNatural :: Natural -> Natural -> Natural
  andNatural = N.naturalAnd
  
  orNatural :: Natural -> Natural -> Natural
  orNatural = N.naturalOr
  
  xorNatural :: Natural -> Natural -> Natural
  xorNatural = N.naturalXor
  
  bitNatural :: Int# -> Natural
  bitNatural i = N.naturalBit# (int2Word# i)
  
  testBitNatural :: Natural -> Int -> Bool
  testBitNatural n i = N.naturalTestBit n (int2Word i)
  
  popCountNatural :: Natural -> Int
  popCountNatural n = word2Int (N.naturalPopCount n)
  
  shiftLNatural :: Natural -> Int -> Natural
  shiftLNatural n i = N.naturalShiftL n (int2Word  i)
  
  shiftRNatural :: Natural -> Int -> Natural
  shiftRNatural n i = N.naturalShiftR n (int2Word i)
  
  -- | @since base-4.12.0.0
  naturalToInteger :: Natural -> Integer
  naturalToInteger = I.integerFromNatural
  
  naturalToWord :: Natural -> Word
  naturalToWord = N.naturalToWord
  
  -- | @since base-4.10.0.0
  naturalFromInteger :: Integer -> Natural
  naturalFromInteger = I.integerToNatural
  
  -- | Construct 'Natural' from 'Word' value.
  --
  -- @since base-4.8.0.0
  wordToNatural :: Word -> Natural
  wordToNatural = N.naturalFromWord
  
  -- | Try downcasting 'Natural' to 'Word' value.
  -- Returns 'Nothing' if value doesn't fit in 'Word'.
  --
  -- @since base-4.8.0.0
  naturalToWordMaybe :: Natural -> Maybe Word
  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 base-4.8.0.0
  powModNatural :: Natural -> Natural -> Natural -> Natural
  powModNatural = N.naturalPowMod
  