{-# LANGUAGE BangPatterns #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE UnboxedTuples #-} {-# LANGUAGE CPP #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE BlockArguments #-} #include "MachDeps.h" -- | -- Module : GHC.Integer.GMP.Internals -- Copyright : (c) Herbert Valerio Riedel 2014 -- License : BSD3 -- -- Maintainer : ghc-devs@haskell.org -- Stability : provisional -- Portability : non-portable (GHC Extensions) -- module GHC.Integer.GMP.Internals ( -- * The 'Integer' type Integer (S#,Jn#,Jp#) , isValidInteger# -- ** Basic 'Integer' operations , module GHC.Integer -- ** Additional 'Integer' operations , gcdInteger , gcdExtInteger , lcmInteger , sqrInteger , powModInteger , recipModInteger -- ** Additional conversion operations to 'Integer' , wordToNegInteger , bigNatToInteger , bigNatToNegInteger -- * The 'BigNat' type , BigNat(..) , GmpLimb, GmpLimb# , GmpSize, GmpSize# -- ** , isValidBigNat# , sizeofBigNat# , zeroBigNat , oneBigNat -- ** Conversions to/from 'BigNat' , byteArrayToBigNat# , wordToBigNat , wordToBigNat2 , bigNatToInt , bigNatToWord , indexBigNat# -- ** 'BigNat' arithmetic operations , plusBigNat , plusBigNatWord , minusBigNat , minusBigNatWord , timesBigNat , timesBigNatWord , sqrBigNat , quotRemBigNat , quotRemBigNatWord , quotBigNatWord , quotBigNat , remBigNat , remBigNatWord , gcdBigNat , gcdBigNatWord -- ** 'BigNat' logic operations , shiftRBigNat , shiftLBigNat , testBitBigNat , clearBitBigNat , complementBitBigNat , setBitBigNat , andBigNat , xorBigNat , popCountBigNat , orBigNat , bitBigNat -- ** 'BigNat' comparison predicates , isZeroBigNat , compareBigNatWord , compareBigNat , eqBigNatWord , eqBigNatWord# , eqBigNat , eqBigNat# , gtBigNatWord# -- * Import/export functions -- ** Compute size of serialisation , sizeInBaseBigNat , sizeInBaseInteger , sizeInBaseWord# -- ** Export , exportBigNatToAddr , exportIntegerToAddr , exportBigNatToMutableByteArray , exportIntegerToMutableByteArray -- ** Import , importBigNatFromAddr , importIntegerFromAddr , importBigNatFromByteArray , importIntegerFromByteArray ) where import GHC.Integer import GHC.Natural import GHC.Num.Integer (Integer(..)) import qualified GHC.Num.Integer as I import qualified GHC.Num.BigNat as B import qualified GHC.Num.Primitives as P import GHC.Types import GHC.Prim import GHC.Exts (runRW#) import Control.Exception {-# COMPLETE S#, Jp#, Jn# #-} {-# DEPRECATED S# "Use IS constructor instead" #-} pattern S# :: Int# -> Integer pattern S# i = IS i fromBN# :: BigNat -> ByteArray# fromBN# (BN# x) = x fromIP :: Integer -> (# () | BigNat #) fromIP (IP x) = (# | BN# x #) fromIP _ = (# () | #) fromIN :: Integer -> (# () | BigNat #) fromIN (IN x) = (# | BN# x #) fromIN _ = (# () | #) {-# DEPRECATED Jp# "Use IP constructor instead" #-} pattern Jp# :: BigNat -> Integer pattern Jp# i <- (fromIP -> (# | i #)) where Jp# i = IP (fromBN# i) {-# DEPRECATED Jn# "Use IN constructor instead" #-} pattern Jn# :: BigNat -> Integer pattern Jn# i <- (fromIN -> (# | i #)) where Jn# i = IN (fromBN# i) {-# DEPRECATED isValidInteger# "Use integerCheck# instead" #-} isValidInteger# :: Integer -> Int# isValidInteger# = I.integerCheck# {-# DEPRECATED gcdInteger "Use integerGcd instead" #-} gcdInteger :: Integer -> Integer -> Integer gcdInteger = I.integerGcd {-# DEPRECATED gcdExtInteger "Use integerGcde instead" #-} gcdExtInteger :: Integer -> Integer -> (# Integer, Integer #) gcdExtInteger a b = case I.integerGcde# a b of (# g, s, _t #) -> (# g, s #) {-# DEPRECATED lcmInteger "Use integerLcm instead" #-} lcmInteger :: Integer -> Integer -> Integer lcmInteger = I.integerLcm {-# DEPRECATED sqrInteger "Use integerSqr instead" #-} sqrInteger :: Integer -> Integer sqrInteger = I.integerSqr {-# DEPRECATED recipModInteger "Use integerRecipMod# instead" #-} recipModInteger :: Integer -> Integer -> Integer recipModInteger x m = case I.integerRecipMod# x (I.integerToNatural m) of (# y | #) -> I.integerFromNatural y (# | () #) -> 0 {-# DEPRECATED powModInteger "Use integerPowMod# instead" #-} powModInteger :: Integer -> Integer -> Integer -> Integer powModInteger b e m = case I.integerPowMod# b e (I.integerToNatural m) of (# r | #) -> I.integerFromNatural r (# | () #) -> 0 {-# DEPRECATED wordToNegInteger "Use integerFromWordNeg# instead" #-} wordToNegInteger :: Word# -> Integer wordToNegInteger = I.integerFromWordNeg# {-# DEPRECATED bigNatToInteger "Use integerFromBigNat# instead" #-} bigNatToInteger :: BigNat -> Integer bigNatToInteger (BN# i) = I.integerFromBigNat# i {-# DEPRECATED bigNatToNegInteger "Use integerFromBigNatNeg# instead" #-} bigNatToNegInteger :: BigNat -> Integer bigNatToNegInteger (BN# i) = I.integerFromBigNatNeg# i type GmpLimb = Word type GmpLimb# = Word# type GmpSize = Int type GmpSize# = Int# {-# DEPRECATED sizeofBigNat# "Use bigNatSize# instead" #-} sizeofBigNat# :: BigNat -> GmpSize# sizeofBigNat# (BN# i) = B.bigNatSize# i {-# DEPRECATED isValidBigNat# "Use bigNatCheck# instead" #-} isValidBigNat# :: BigNat -> Int# isValidBigNat# (BN# i) = B.bigNatCheck# i {-# DEPRECATED zeroBigNat "Use bigNatZero instead" #-} zeroBigNat :: BigNat zeroBigNat = B.bigNatZero {-# DEPRECATED oneBigNat "Use bigNatOne instead" #-} oneBigNat :: BigNat oneBigNat = B.bigNatOne {-# DEPRECATED plusBigNat "Use bigNatAdd instead" #-} plusBigNat :: BigNat -> BigNat -> BigNat plusBigNat (BN# a) (BN# b) = BN# (B.bigNatAdd a b) {-# DEPRECATED plusBigNatWord "Use bigNatAddWord# instead" #-} plusBigNatWord :: BigNat -> GmpLimb# -> BigNat plusBigNatWord (BN# a) w = BN# (B.bigNatAddWord# a w) {-# DEPRECATED minusBigNat "Use bigNatSub instead" #-} minusBigNat :: BigNat -> BigNat -> BigNat minusBigNat (BN# a) (BN# b) = case B.bigNatSub a b of (# (# #) | #) -> throw Underflow (# | r #) -> BN# r {-# DEPRECATED minusBigNatWord "Use bigNatSubWord# instead" #-} minusBigNatWord :: BigNat -> GmpLimb# -> BigNat minusBigNatWord (BN# a) b = case B.bigNatSubWord# a b of (# (# #) | #) -> throw Underflow (# | r #) -> BN# r {-# DEPRECATED timesBigNat "Use bigNatMul instead" #-} timesBigNat :: BigNat -> BigNat -> BigNat timesBigNat (BN# a) (BN# b) = BN# (B.bigNatMul a b) {-# DEPRECATED timesBigNatWord "Use bigNatMulWord# instead" #-} timesBigNatWord :: BigNat -> GmpLimb# -> BigNat timesBigNatWord (BN# a) w = BN# (B.bigNatMulWord# a w) {-# DEPRECATED sqrBigNat "Use bigNatSqr instead" #-} sqrBigNat :: BigNat -> BigNat sqrBigNat (BN# a) = BN# (B.bigNatSqr a) {-# DEPRECATED quotRemBigNat "Use bigNatQuotRem# instead" #-} quotRemBigNat :: BigNat -> BigNat -> (# BigNat,BigNat #) quotRemBigNat (BN# a) (BN# b) = case B.bigNatQuotRem# a b of (# q, r #) -> (# BN# q, BN# r #) {-# DEPRECATED quotRemBigNatWord "Use bigNatQuotRemWord# instead" #-} quotRemBigNatWord :: BigNat -> GmpLimb# -> (# BigNat, GmpLimb# #) quotRemBigNatWord (BN# a) b = case B.bigNatQuotRemWord# a b of (# q, r #) -> (# BN# q, r #) {-# DEPRECATED quotBigNat "Use bigNatQuot instead" #-} quotBigNat :: BigNat -> BigNat -> BigNat quotBigNat (BN# a) (BN# b) = BN# (B.bigNatQuot a b) {-# DEPRECATED quotBigNatWord "Use bigNatQuotWord# instead" #-} quotBigNatWord :: BigNat -> GmpLimb# -> BigNat quotBigNatWord (BN# a) b = BN# (B.bigNatQuotWord# a b) {-# DEPRECATED remBigNat "Use bigNatRem instead" #-} remBigNat :: BigNat -> BigNat -> BigNat remBigNat (BN# a) (BN# b) = BN# (B.bigNatRem a b) {-# DEPRECATED remBigNatWord "Use bigNatRemWord# instead" #-} remBigNatWord :: BigNat -> GmpLimb# -> Word# remBigNatWord (BN# a) b = B.bigNatRemWord# a b {-# DEPRECATED gcdBigNatWord "Use bigNatGcdWord# instead" #-} gcdBigNatWord :: BigNat -> Word# -> Word# gcdBigNatWord (BN# a) b = B.bigNatGcdWord# a b {-# DEPRECATED gcdBigNat "Use bigNatGcd instead" #-} gcdBigNat:: BigNat -> BigNat -> BigNat gcdBigNat (BN# a) (BN# b) = BN# (B.bigNatGcd a b) {-# DEPRECATED shiftRBigNat "Use bigNatShiftR# instead" #-} shiftRBigNat :: BigNat -> Int# -> BigNat shiftRBigNat (BN# a) i = BN# (B.bigNatShiftR# a (int2Word# i)) {-# DEPRECATED shiftLBigNat "Use bigNatShiftL# instead" #-} shiftLBigNat :: BigNat -> Int# -> BigNat shiftLBigNat (BN# a) i = BN# (B.bigNatShiftL# a (int2Word# i)) {-# DEPRECATED testBitBigNat "Use bigNatTestBit# instead" #-} testBitBigNat :: BigNat -> Int# -> Bool testBitBigNat (BN# a) i = isTrue# (B.bigNatTestBit# a (int2Word# i)) {-# DEPRECATED clearBitBigNat "Use bigNatClearBit# instead" #-} clearBitBigNat :: BigNat -> Int# -> BigNat clearBitBigNat (BN# a) i = BN# (B.bigNatClearBit# a (int2Word# i)) {-# DEPRECATED complementBitBigNat "Use bigNatComplementBit# instead" #-} complementBitBigNat :: BigNat -> Int# -> BigNat complementBitBigNat (BN# a) i = BN# (B.bigNatComplementBit# a (int2Word# i)) {-# DEPRECATED setBitBigNat "Use bigNatSetBit# instead" #-} setBitBigNat :: BigNat -> Int# -> BigNat setBitBigNat (BN# a) i = BN# (B.bigNatSetBit# a (int2Word# i)) {-# DEPRECATED andBigNat "Use bigNatAnd instead" #-} andBigNat :: BigNat -> BigNat -> BigNat andBigNat (BN# a) (BN# b) = BN# (B.bigNatAnd a b) {-# DEPRECATED orBigNat "Use bigNatOr instead" #-} orBigNat :: BigNat -> BigNat -> BigNat orBigNat (BN# a) (BN# b) = BN# (B.bigNatOr a b) {-# DEPRECATED xorBigNat "Use bigNatXor instead" #-} xorBigNat :: BigNat -> BigNat -> BigNat xorBigNat (BN# a) (BN# b) = BN# (B.bigNatXor a b) {-# DEPRECATED popCountBigNat "Use bigNatPopCount# instead" #-} popCountBigNat :: BigNat -> Int# popCountBigNat (BN# a) = word2Int# (B.bigNatPopCount# a) {-# DEPRECATED bitBigNat "Use bigNatBit# instead" #-} bitBigNat :: Int# -> BigNat bitBigNat i = BN# (B.bigNatBit# (int2Word# i)) {-# DEPRECATED isZeroBigNat "Use bigNatIsZero instead" #-} isZeroBigNat :: BigNat -> Bool isZeroBigNat (BN# a) = B.bigNatIsZero a {-# DEPRECATED compareBigNat "Use bigNatCompare instead" #-} compareBigNat :: BigNat -> BigNat -> Ordering compareBigNat (BN# a) (BN# b) = B.bigNatCompare a b {-# DEPRECATED compareBigNatWord "Use bigNatCompareWord# instead" #-} compareBigNatWord :: BigNat -> GmpLimb# -> Ordering compareBigNatWord (BN# a) w = B.bigNatCompareWord# a w {-# DEPRECATED eqBigNatWord "Use bigNatEqWord# instead" #-} eqBigNatWord :: BigNat -> GmpLimb# -> Bool eqBigNatWord (BN# a) w = isTrue# (B.bigNatEqWord# a w) {-# DEPRECATED eqBigNatWord# "Use bigNatEqWord# instead" #-} eqBigNatWord# :: BigNat -> GmpLimb# -> Int# eqBigNatWord# (BN# a) w = B.bigNatEqWord# a w {-# DEPRECATED eqBigNat# "Use bigNatEq# instead" #-} eqBigNat# :: BigNat -> BigNat -> Int# eqBigNat# (BN# a) (BN# b) = B.bigNatEq# a b {-# DEPRECATED eqBigNat "Use bigNatEq instead" #-} eqBigNat :: BigNat -> BigNat -> Bool eqBigNat (BN# a) (BN# b) = B.bigNatEq a b {-# DEPRECATED gtBigNatWord# "Use bigNatGtWord# instead" #-} gtBigNatWord# :: BigNat -> GmpLimb# -> Int# gtBigNatWord# (BN# a) w = B.bigNatGtWord# a w {-# DEPRECATED sizeInBaseBigNat "Use bigNatSizeInBase# instead" #-} sizeInBaseBigNat :: BigNat -> Int# -> Word# sizeInBaseBigNat (BN# a) b = B.bigNatSizeInBase# (int2Word# b) a {-# DEPRECATED sizeInBaseInteger "Use integerSizeInBase# instead" #-} sizeInBaseInteger :: Integer -> Int# -> Word# sizeInBaseInteger i b = I.integerSizeInBase# (int2Word# b) i {-# DEPRECATED sizeInBaseWord# "Use wordSizeInBase# instead" #-} sizeInBaseWord# :: Word# -> Int# -> Word# sizeInBaseWord# a b = P.wordSizeInBase# (int2Word# b) a {-# DEPRECATED importBigNatFromAddr "Use bigNatFromAddr# instead" #-} importBigNatFromAddr :: Addr# -> Word# -> Int# -> IO BigNat importBigNatFromAddr addr sz endian = IO \s -> case B.bigNatFromAddr# sz addr endian s of (# s', b #) -> (# s', BN# b #) {-# DEPRECATED exportBigNatToAddr "Use bigNatToAddr# instead" #-} exportBigNatToAddr :: BigNat -> Addr# -> Int# -> IO Word exportBigNatToAddr (BN# b) addr endian = IO \s -> case B.bigNatToAddr# b addr endian s of (# s', w #) -> (# s', W# w #) {-# DEPRECATED importIntegerFromAddr "Use integerFromAddr# instead" #-} importIntegerFromAddr :: Addr# -> Word# -> Int# -> IO Integer importIntegerFromAddr addr sz endian = IO \s -> case I.integerFromAddr# sz addr endian s of (# s', i #) -> (# s', i #) {-# DEPRECATED exportIntegerToAddr "Use integerToAddr# instead" #-} exportIntegerToAddr :: Integer -> Addr# -> Int# -> IO Word exportIntegerToAddr i addr endian = IO \s -> case I.integerToAddr# i addr endian s of (# s', w #) -> (# s', W# w #) wordToBigNat :: Word# -> BigNat wordToBigNat w = BN# (B.bigNatFromWord# w) wordToBigNat2 :: Word# -> Word# -> BigNat wordToBigNat2 h l = BN# (B.bigNatFromWord2# h l) bigNatToInt :: BigNat -> Int# bigNatToInt (BN# b) = B.bigNatToInt# b bigNatToWord :: BigNat -> Word# bigNatToWord (BN# b) = B.bigNatToWord# b {-# DEPRECATED indexBigNat# "Use bigNatIndex# instead" #-} indexBigNat# :: BigNat -> GmpSize# -> GmpLimb# indexBigNat# (BN# b) i = B.bigNatIndex# b i {-# DEPRECATED importBigNatFromByteArray "Use bigNatFromByteArray# instead" #-} importBigNatFromByteArray :: ByteArray# -> Word# -> Word# -> Int# -> BigNat importBigNatFromByteArray ba off sz endian = case runRW# (B.bigNatFromByteArray# sz ba off endian) of (# _, r #) -> BN# r {-# DEPRECATED exportBigNatToMutableByteArray "Use bigNatToMutableByteArray# instead" #-} exportBigNatToMutableByteArray :: BigNat -> MutableByteArray# RealWorld -> Word# -> Int# -> IO Word exportBigNatToMutableByteArray (BN# ba) mba off endian = IO (\s -> case B.bigNatToMutableByteArray# ba mba off endian s of (# s', r #) -> (# s', W# r #)) {-# DEPRECATED importIntegerFromByteArray "Use integerFromByteArray# instead" #-} importIntegerFromByteArray :: ByteArray# -> Word# -> Word# -> Int# -> Integer importIntegerFromByteArray ba off sz endian = case runRW# (I.integerFromByteArray# sz ba off endian) of (# _, r #) -> r {-# DEPRECATED exportIntegerToMutableByteArray "Use integerToMutableByteArray# instead" #-} exportIntegerToMutableByteArray :: Integer -> MutableByteArray# RealWorld -> Word# -> Int# -> IO Word exportIntegerToMutableByteArray i mba off endian = IO (\s -> case I.integerToMutableByteArray# i mba off endian s of (# s', r #) -> (# s', W# r #)) {-# DEPRECATED byteArrayToBigNat# "Use bigNatFromWordArray instead" #-} byteArrayToBigNat# :: ByteArray# -> GmpSize# -> BigNat byteArrayToBigNat# ba n = B.bigNatFromWordArray ba (int2Word# n)