{-|
Module      : Z.Crypto.MPI
Description : Multiple Precision Integer
Copyright   : Dong Han, 2021
License     : BSD
Maintainer  : winterland1989@gmail.com
Stability   : experimental
Portability : non-portable

This module provide Botan's Multiple Precision Integer, featuring constant-time operations, which is suit for cryptograph usage.

-}
module Z.Crypto.MPI
  ( -- * MPI
    MPI, fromCInt, toWord32, byteSize, Z.Crypto.MPI.bitSize
    -- * MPI Builder & Parser
  , toHex, toDecimal, fromHex, fromDecimal
    -- * MPI Predicator
  , isNegative, isZero, isOdd, isEven, isPrim
    -- * MPI specific
  , mulMod, powMod, modInverse, Z.Crypto.MPI.gcd
    -- * Random MPI
  , randBits, randRange
    -- * Internal
  , copyMPI
  , newMPI
  , unsafeNewMPI
  , newMPI'
  , unsafeNewMPI'
  , withMPI
  , unsafeWithMPI
  ) where

import           Control.Monad
import           Data.Bits
import qualified Data.Scientific           as Scientific
import           Data.Word
import           GHC.Exts
import           GHC.Generics
import           GHC.Integer.GMP.Internals
import           GHC.Real
import           System.IO.Unsafe          (unsafeDupablePerformIO)
import           Z.Botan.Exception
import           Z.Botan.FFI
import           Z.Crypto.RNG
import qualified Z.Data.Array              as A
import           Z.Data.ASCII
import qualified Z.Data.Builder            as B
import           Z.Data.JSON               (JSON (..), Value (..), fail',
                                            withBoundedScientific)
import qualified Z.Data.Parser             as P
import qualified Z.Data.Text               as T
import qualified Z.Data.Vector.Base        as V
import           Z.Foreign                 (CInt, CSize,
                                            MutablePrimArray (MutablePrimArray),
                                            PrimArray (..), allocPrimUnsafe,
                                            newPrimArray, unsafeFreezePrimArray)

-- | Opaque Botan Multiple Precision Integers.
newtype MPI = MPI BotanStruct

instance Eq MPI where
    {-# INLINE (==) #-}
    MPI
a == :: MPI -> MPI -> Bool
== MPI
b =
        MPI -> (BotanStructT -> IO Bool) -> Bool
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
a ((BotanStructT -> IO Bool) -> Bool)
-> (BotanStructT -> IO Bool) -> Bool
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsa ->
            MPI -> (BotanStructT -> IO Bool) -> IO Bool
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
b ((BotanStructT -> IO Bool) -> IO Bool)
-> (BotanStructT -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsb -> do
                CInt
r <- BotanStructT -> BotanStructT -> IO CInt
botan_mp_equal BotanStructT
btsa BotanStructT
btsb
                Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$! CInt
r CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1

instance Ord MPI where
    {-# INLINE compare #-}
    MPI
a compare :: MPI -> MPI -> Ordering
`compare` MPI
b =
        MPI -> (BotanStructT -> IO Ordering) -> Ordering
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
a ((BotanStructT -> IO Ordering) -> Ordering)
-> (BotanStructT -> IO Ordering) -> Ordering
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsa ->
            MPI -> (BotanStructT -> IO Ordering) -> IO Ordering
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
b ((BotanStructT -> IO Ordering) -> IO Ordering)
-> (BotanStructT -> IO Ordering) -> IO Ordering
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsb -> do
                (CInt
r, CInt
_) <- (MBA# CInt -> IO CInt) -> IO (CInt, CInt)
forall a b. Prim a => (MBA# CInt -> IO b) -> IO (a, b)
allocPrimUnsafe ((MBA# CInt -> IO CInt) -> IO (CInt, CInt))
-> (MBA# CInt -> IO CInt) -> IO (CInt, CInt)
forall a b. (a -> b) -> a -> b
$ \ MBA# CInt
r -> MBA# CInt -> BotanStructT -> BotanStructT -> IO CInt
botan_mp_cmp MBA# CInt
r BotanStructT
btsa BotanStructT
btsb
                Ordering -> IO Ordering
forall (m :: * -> *) a. Monad m => a -> m a
return (Ordering -> IO Ordering) -> Ordering -> IO Ordering
forall a b. (a -> b) -> a -> b
$! case (CInt
r :: CInt) of
                    CInt
1 -> Ordering
GT
                    CInt
0 -> Ordering
EQ
                    CInt
_ -> Ordering
LT

instance Num MPI where
    {-# INLINE (+) #-}
    MPI
a + :: MPI -> MPI -> MPI
+ MPI
b = IO MPI -> MPI
forall a. IO a -> a
unsafeDupablePerformIO (IO MPI -> MPI) -> IO MPI -> MPI
forall a b. (a -> b) -> a -> b
$ do
        MPI -> (BotanStructT -> IO MPI) -> IO MPI
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
a ((BotanStructT -> IO MPI) -> IO MPI)
-> (BotanStructT -> IO MPI) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsa ->
            MPI -> (BotanStructT -> IO MPI) -> IO MPI
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
b ((BotanStructT -> IO MPI) -> IO MPI)
-> (BotanStructT -> IO MPI) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsb ->
                (BotanStructT -> IO CInt) -> IO MPI
forall a. (BotanStructT -> IO a) -> IO MPI
newMPI ((BotanStructT -> IO CInt) -> IO MPI)
-> (BotanStructT -> IO CInt) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsr -> BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_mp_add BotanStructT
btsr BotanStructT
btsa BotanStructT
btsb
    {-# INLINE (-) #-}
    MPI
a - :: MPI -> MPI -> MPI
- MPI
b = IO MPI -> MPI
forall a. IO a -> a
unsafeDupablePerformIO (IO MPI -> MPI) -> IO MPI -> MPI
forall a b. (a -> b) -> a -> b
$ do
        MPI -> (BotanStructT -> IO MPI) -> IO MPI
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
a ((BotanStructT -> IO MPI) -> IO MPI)
-> (BotanStructT -> IO MPI) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsa ->
            MPI -> (BotanStructT -> IO MPI) -> IO MPI
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
b ((BotanStructT -> IO MPI) -> IO MPI)
-> (BotanStructT -> IO MPI) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsb ->
                (BotanStructT -> IO CInt) -> IO MPI
forall a. (BotanStructT -> IO a) -> IO MPI
newMPI ((BotanStructT -> IO CInt) -> IO MPI)
-> (BotanStructT -> IO CInt) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsr -> BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_mp_sub BotanStructT
btsr BotanStructT
btsa BotanStructT
btsb
    {-# INLINE (*) #-}
    MPI
a * :: MPI -> MPI -> MPI
* MPI
b = IO MPI -> MPI
forall a. IO a -> a
unsafeDupablePerformIO (IO MPI -> MPI) -> IO MPI -> MPI
forall a b. (a -> b) -> a -> b
$ do
        MPI -> (BotanStructT -> IO MPI) -> IO MPI
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
a ((BotanStructT -> IO MPI) -> IO MPI)
-> (BotanStructT -> IO MPI) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsa ->
            MPI -> (BotanStructT -> IO MPI) -> IO MPI
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
b ((BotanStructT -> IO MPI) -> IO MPI)
-> (BotanStructT -> IO MPI) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsb ->
                (BotanStructT -> IO CInt) -> IO MPI
forall a. (BotanStructT -> IO a) -> IO MPI
newMPI ((BotanStructT -> IO CInt) -> IO MPI)
-> (BotanStructT -> IO CInt) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsr -> BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_mp_mul BotanStructT
btsr BotanStructT
btsa BotanStructT
btsb

    {-# INLINE negate #-}

    negate :: MPI -> MPI
negate MPI
a = MPI -> (BotanStructT -> IO MPI) -> MPI
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
a ((BotanStructT -> IO MPI) -> MPI)
-> (BotanStructT -> IO MPI) -> MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsa ->
        (BotanStructT -> IO CInt) -> IO MPI
forall a. (BotanStructT -> IO a) -> IO MPI
newMPI (\ BotanStructT
bts -> do
            IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (BotanStructT -> BotanStructT -> IO CInt
botan_mp_set_from_mp BotanStructT
bts BotanStructT
btsa)
            BotanStructT -> IO CInt
botan_mp_flip_sign BotanStructT
bts)

    {-# INLINE abs #-}
    abs :: MPI -> MPI
abs MPI
mp | MPI -> Bool
isNegative MPI
mp = MPI -> MPI
forall a. Num a => a -> a
negate MPI
mp
           | Bool
otherwise = MPI
mp

    {-# INLINE signum #-}
    signum :: MPI -> MPI
signum MPI
mp = case MPI
mp MPI -> MPI -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` MPI
zero of
        Ordering
LT -> -MPI
1
        Ordering
EQ -> MPI
0
        Ordering
_  -> MPI
1

    {-# INLINE fromInteger #-}
    fromInteger :: Integer -> MPI
fromInteger Integer
c
        | Integer
c Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = MPI
zero
        | Bool
otherwise = IO MPI -> MPI
forall a. IO a -> a
unsafeDupablePerformIO (IO MPI -> MPI) -> IO MPI -> MPI
forall a b. (a -> b) -> a -> b
$ do
            mpa :: MutablePrimArray RealWorld Word8
mpa@(MutablePrimArray MBA# CInt
mba#)<- Int -> IO (MutablePrimArray (PrimState IO) Word8)
forall (m :: * -> *) a.
(PrimMonad m, Prim a) =>
Int -> m (MutablePrimArray (PrimState m) a)
newPrimArray (Int# -> Int
I# (Word# -> Int#
word2Int# Word#
siz#))
            IO Word -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Integer -> MBA# CInt -> Word# -> Int# -> IO Word
exportIntegerToMutableByteArray Integer
c MBA# CInt
mba# Word#
0## Int#
1#)
            (PrimArray ByteArray#
ba# :: PrimArray Word8) <- MutablePrimArray (PrimState IO) Word8 -> IO (PrimArray Word8)
forall (m :: * -> *) a.
PrimMonad m =>
MutablePrimArray (PrimState m) a -> m (PrimArray a)
unsafeFreezePrimArray MutablePrimArray RealWorld Word8
MutablePrimArray (PrimState IO) Word8
mpa
            MPI
r <- (BotanStructT -> IO CInt) -> IO MPI
forall a. (BotanStructT -> IO a) -> IO MPI
newMPI ((BotanStructT -> IO CInt) -> IO MPI)
-> (BotanStructT -> IO CInt) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts -> BotanStructT -> ByteArray# -> Int -> Int -> IO CInt
hs_botan_mp_from_bin BotanStructT
bts ByteArray#
ba# Int
0 (Int# -> Int
I# (Word# -> Int#
word2Int# Word#
siz#))
            MPI -> IO MPI
forall (m :: * -> *) a. Monad m => a -> m a
return (MPI -> IO MPI) -> MPI -> IO MPI
forall a b. (a -> b) -> a -> b
$! if Integer
c Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 then MPI -> MPI
forall a. Num a => a -> a
negate MPI
r else MPI
r
      where
        siz# :: Word#
siz# = Integer -> Int# -> Word#
sizeInBaseInteger Integer
c Int#
256#

instance Real MPI where
    {-# INLINE toRational #-}
    toRational :: MPI -> Rational
toRational MPI
mp = MPI -> Integer
forall a. Integral a => a -> Integer
toInteger MPI
mp Integer -> Integer -> Rational
forall a. a -> a -> Ratio a
:% Integer
1

instance Enum MPI where
    succ :: MPI -> MPI
succ MPI
x               = MPI
x MPI -> MPI -> MPI
forall a. Num a => a -> a -> a
+ MPI
1
    pred :: MPI -> MPI
pred MPI
x               = MPI
x MPI -> MPI -> MPI
forall a. Num a => a -> a -> a
- MPI
1
    toEnum :: Int -> MPI
toEnum               = Int -> MPI
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    fromEnum :: MPI -> Int
fromEnum             = MPI -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    {-# INLINE enumFrom #-}
    {-# INLINE enumFromThen #-}
    {-# INLINE enumFromTo #-}
    {-# INLINE enumFromThenTo #-}
    enumFrom :: MPI -> [MPI]
enumFrom MPI
x             = MPI -> MPI -> [MPI]
enumDeltaMPI   MPI
x MPI
1
    enumFromThen :: MPI -> MPI -> [MPI]
enumFromThen MPI
x MPI
y       = MPI -> MPI -> [MPI]
enumDeltaMPI   MPI
x (MPI
yMPI -> MPI -> MPI
forall a. Num a => a -> a -> a
-MPI
x)
    enumFromTo :: MPI -> MPI -> [MPI]
enumFromTo MPI
x MPI
lim       = MPI -> MPI -> MPI -> [MPI]
enumDeltaToMPI MPI
x MPI
1     MPI
lim
    enumFromThenTo :: MPI -> MPI -> MPI -> [MPI]
enumFromThenTo MPI
x MPI
y MPI
lim = MPI -> MPI -> MPI -> [MPI]
enumDeltaToMPI MPI
x (MPI
yMPI -> MPI -> MPI
forall a. Num a => a -> a -> a
-MPI
x) MPI
lim

instance JSON MPI where
    {-# INLINE fromValue #-}
    fromValue :: Value -> Converter MPI
fromValue = Text -> (Scientific -> Converter MPI) -> Value -> Converter MPI
forall a.
Text -> (Scientific -> Converter a) -> Value -> Converter a
withBoundedScientific Text
"Z.Crypto.MPI.MPI" ((Scientific -> Converter MPI) -> Value -> Converter MPI)
-> (Scientific -> Converter MPI) -> Value -> Converter MPI
forall a b. (a -> b) -> a -> b
$ \ Scientific
n ->
        case Scientific -> Either Double Integer
forall r i. (RealFloat r, Integral i) => Scientific -> Either r i
Scientific.floatingOrInteger Scientific
n :: Either Double Integer of
            Right Integer
x -> MPI -> Converter MPI
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Integer -> MPI
forall a. Num a => Integer -> a
fromInteger Integer
x)
            Left Double
_  -> Text -> Converter MPI
forall a. Text -> Converter a
fail' (Text -> Converter MPI)
-> (Builder () -> Text) -> Builder () -> Converter MPI
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder () -> Text
forall a. Builder a -> Text
B.unsafeBuildText (Builder () -> Converter MPI) -> Builder () -> Converter MPI
forall a b. (a -> b) -> a -> b
$ do
                Builder ()
"converting Integer failed, unexpected floating number "
                Scientific -> Builder ()
B.scientific Scientific
n
    {-# INLINE toValue #-}
    toValue :: MPI -> Value
toValue = Scientific -> Value
Number (Scientific -> Value) -> (MPI -> Scientific) -> MPI -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MPI -> Scientific
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    {-# INLINE encodeJSON #-}
    encodeJSON :: MPI -> Builder ()
encodeJSON = MPI -> Builder ()
toDecimal


-- These RULES are copied from GHC.Enum
{-# RULES
"enumDeltaMPI"      [~1] forall x y.   enumDeltaMPI x y         = build (\c _ -> enumDeltaMPIFB c x y)
"efdtMPI"           [~1] forall x d l. enumDeltaToMPI x d l     = build (\c n -> enumDeltaToMPIFB  c n x d l)
"efdtMPI1"          [~1] forall x l.   enumDeltaToMPI x 1 l     = build (\c n -> enumDeltaToMPI1FB c n x l)

"enumDeltaToMPI1FB" [1] forall c n x.  enumDeltaToMPIFB c n x 1 = enumDeltaToMPI1FB c n x

"enumDeltaMPI"      [1] enumDeltaMPIFB    (:)     = enumDeltaMPI
"enumDeltaToMPI"    [1] enumDeltaToMPIFB  (:) []  = enumDeltaToMPI
"enumDeltaToMPI1"   [1] enumDeltaToMPI1FB (:) []  = enumDeltaToMPI1
 #-}

{-# INLINE [0] enumDeltaMPIFB #-}
-- See Note [Inline FB functions] in GHC.List
enumDeltaMPIFB :: (MPI -> b -> b) -> MPI -> MPI -> b
enumDeltaMPIFB :: (MPI -> b -> b) -> MPI -> MPI -> b
enumDeltaMPIFB MPI -> b -> b
c MPI
x0 MPI
d = MPI -> b
go MPI
x0
  where go :: MPI -> b
go MPI
x = MPI
x MPI -> b -> b
`seq` (MPI
x MPI -> b -> b
`c` MPI -> b
go (MPI
xMPI -> MPI -> MPI
forall a. Num a => a -> a -> a
+MPI
d))

{-# NOINLINE [1] enumDeltaMPI #-}
enumDeltaMPI :: MPI -> MPI -> [MPI]
enumDeltaMPI :: MPI -> MPI -> [MPI]
enumDeltaMPI MPI
x MPI
d = MPI
x MPI -> [MPI] -> [MPI]
`seq` (MPI
x MPI -> [MPI] -> [MPI]
forall a. a -> [a] -> [a]
: MPI -> MPI -> [MPI]
enumDeltaMPI (MPI
xMPI -> MPI -> MPI
forall a. Num a => a -> a -> a
+MPI
d) MPI
d)
-- strict accumulator, so
--     head (drop 1000000 [1 .. ]
-- works

{-# INLINE [0] enumDeltaToMPIFB #-}
-- See Note [Inline FB functions] in GHC.List
-- Don't inline this until RULE "enumDeltaToMPI" has had a chance to fire
enumDeltaToMPIFB :: (MPI -> a -> a) -> a
                     -> MPI -> MPI -> MPI -> a
enumDeltaToMPIFB :: (MPI -> a -> a) -> a -> MPI -> MPI -> MPI -> a
enumDeltaToMPIFB MPI -> a -> a
c a
n MPI
x MPI
delta MPI
lim
  | MPI
delta MPI -> MPI -> Bool
forall a. Ord a => a -> a -> Bool
>= MPI
0 = (MPI -> a -> a) -> a -> MPI -> MPI -> MPI -> a
forall a. (MPI -> a -> a) -> a -> MPI -> MPI -> MPI -> a
up_fb MPI -> a -> a
c a
n MPI
x MPI
delta MPI
lim
  | Bool
otherwise  = (MPI -> a -> a) -> a -> MPI -> MPI -> MPI -> a
forall a. (MPI -> a -> a) -> a -> MPI -> MPI -> MPI -> a
dn_fb MPI -> a -> a
c a
n MPI
x MPI
delta MPI
lim

{-# INLINE [0] enumDeltaToMPI1FB #-}
-- See Note [Inline FB functions] in GHC.List
-- Don't inline this until RULE "enumDeltaToMPI" has had a chance to fire
enumDeltaToMPI1FB :: (MPI -> a -> a) -> a
                      -> MPI -> MPI -> a
enumDeltaToMPI1FB :: (MPI -> a -> a) -> a -> MPI -> MPI -> a
enumDeltaToMPI1FB MPI -> a -> a
c a
n MPI
x0 MPI
lim = MPI -> a
go (MPI
x0 :: MPI)
                      where
                        go :: MPI -> a
go MPI
x | MPI
x MPI -> MPI -> Bool
forall a. Ord a => a -> a -> Bool
> MPI
lim   = a
n
                             | Bool
otherwise = MPI
x MPI -> a -> a
`c` MPI -> a
go (MPI
xMPI -> MPI -> MPI
forall a. Num a => a -> a -> a
+MPI
1)

{-# NOINLINE [1] enumDeltaToMPI #-}
enumDeltaToMPI :: MPI -> MPI -> MPI -> [MPI]
enumDeltaToMPI :: MPI -> MPI -> MPI -> [MPI]
enumDeltaToMPI MPI
x MPI
delta MPI
lim
  | MPI
delta MPI -> MPI -> Bool
forall a. Ord a => a -> a -> Bool
>= MPI
0 = MPI -> MPI -> MPI -> [MPI]
up_list MPI
x MPI
delta MPI
lim
  | Bool
otherwise  = MPI -> MPI -> MPI -> [MPI]
dn_list MPI
x MPI
delta MPI
lim

{-# NOINLINE [1] enumDeltaToMPI1 #-}
enumDeltaToMPI1 :: MPI -> MPI -> [MPI]
-- Special case for Delta = 1
enumDeltaToMPI1 :: MPI -> MPI -> [MPI]
enumDeltaToMPI1 MPI
x0 MPI
lim = MPI -> [MPI]
go (MPI
x0 :: MPI)
                      where
                        go :: MPI -> [MPI]
go MPI
x | MPI
x MPI -> MPI -> Bool
forall a. Ord a => a -> a -> Bool
> MPI
lim   = []
                             | Bool
otherwise = MPI
x MPI -> [MPI] -> [MPI]
forall a. a -> [a] -> [a]
: MPI -> [MPI]
go (MPI
xMPI -> MPI -> MPI
forall a. Num a => a -> a -> a
+MPI
1)

up_fb :: (MPI -> a -> a) -> a -> MPI -> MPI -> MPI -> a
up_fb :: (MPI -> a -> a) -> a -> MPI -> MPI -> MPI -> a
up_fb MPI -> a -> a
c a
n MPI
x0 MPI
delta MPI
lim = MPI -> a
go (MPI
x0 :: MPI)
                      where
                        go :: MPI -> a
go MPI
x | MPI
x MPI -> MPI -> Bool
forall a. Ord a => a -> a -> Bool
> MPI
lim   = a
n
                             | Bool
otherwise = MPI
x MPI -> a -> a
`c` MPI -> a
go (MPI
xMPI -> MPI -> MPI
forall a. Num a => a -> a -> a
+MPI
delta)
dn_fb :: (MPI -> a -> a) -> a -> MPI -> MPI -> MPI -> a
dn_fb :: (MPI -> a -> a) -> a -> MPI -> MPI -> MPI -> a
dn_fb MPI -> a -> a
c a
n MPI
x0 MPI
delta MPI
lim = MPI -> a
go (MPI
x0 :: MPI)
                      where
                        go :: MPI -> a
go MPI
x | MPI
x MPI -> MPI -> Bool
forall a. Ord a => a -> a -> Bool
< MPI
lim   = a
n
                             | Bool
otherwise = MPI
x MPI -> a -> a
`c` MPI -> a
go (MPI
xMPI -> MPI -> MPI
forall a. Num a => a -> a -> a
+MPI
delta)

up_list :: MPI -> MPI -> MPI -> [MPI]
up_list :: MPI -> MPI -> MPI -> [MPI]
up_list MPI
x0 MPI
delta MPI
lim = MPI -> [MPI]
go (MPI
x0 :: MPI)
                    where
                        go :: MPI -> [MPI]
go MPI
x | MPI
x MPI -> MPI -> Bool
forall a. Ord a => a -> a -> Bool
> MPI
lim   = []
                             | Bool
otherwise = MPI
x MPI -> [MPI] -> [MPI]
forall a. a -> [a] -> [a]
: MPI -> [MPI]
go (MPI
xMPI -> MPI -> MPI
forall a. Num a => a -> a -> a
+MPI
delta)
dn_list :: MPI -> MPI -> MPI -> [MPI]
dn_list :: MPI -> MPI -> MPI -> [MPI]
dn_list MPI
x0 MPI
delta MPI
lim = MPI -> [MPI]
go (MPI
x0 :: MPI)
                    where
                        go :: MPI -> [MPI]
go MPI
x | MPI
x MPI -> MPI -> Bool
forall a. Ord a => a -> a -> Bool
< MPI
lim   = []
                             | Bool
otherwise = MPI
x MPI -> [MPI] -> [MPI]
forall a. a -> [a] -> [a]
: MPI -> [MPI]
go (MPI
xMPI -> MPI -> MPI
forall a. Num a => a -> a -> a
+MPI
delta)

instance Integral MPI where
    {-# INLINE quotRem #-}
    MPI
a quotRem :: MPI -> MPI -> (MPI, MPI)
`quotRem` MPI
b =
        MPI -> (BotanStructT -> IO (MPI, MPI)) -> (MPI, MPI)
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
a ((BotanStructT -> IO (MPI, MPI)) -> (MPI, MPI))
-> (BotanStructT -> IO (MPI, MPI)) -> (MPI, MPI)
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsa ->
            MPI -> (BotanStructT -> IO (MPI, MPI)) -> IO (MPI, MPI)
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
b ((BotanStructT -> IO (MPI, MPI)) -> IO (MPI, MPI))
-> (BotanStructT -> IO (MPI, MPI)) -> IO (MPI, MPI)
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsb ->
                (BotanStructT -> IO MPI) -> IO (MPI, MPI)
forall a. (BotanStructT -> IO a) -> IO (MPI, a)
newMPI' ((BotanStructT -> IO MPI) -> IO (MPI, MPI))
-> (BotanStructT -> IO MPI) -> IO (MPI, MPI)
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
q ->
                    (BotanStructT -> IO CInt) -> IO MPI
forall a. (BotanStructT -> IO a) -> IO MPI
newMPI ((BotanStructT -> IO CInt) -> IO MPI)
-> (BotanStructT -> IO CInt) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
r ->
                        BotanStructT
-> BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_mp_div BotanStructT
q BotanStructT
r BotanStructT
btsa BotanStructT
btsb

    {-# INLINE toInteger #-}
    toInteger :: MPI -> Integer
toInteger MPI
mp
        | MPI -> Bool
isZero MPI
mp = Integer
0
        | Bool
otherwise = MPI -> (BotanStructT -> IO Integer) -> Integer
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
mp ((BotanStructT -> IO Integer) -> Integer)
-> (BotanStructT -> IO Integer) -> Integer
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts -> do
            mpa :: MutablePrimArray RealWorld Word8
mpa@(MutablePrimArray MBA# CInt
mba#) <- Int -> IO (MutablePrimArray (PrimState IO) Word8)
forall (m :: * -> *) a.
(PrimMonad m, Prim a) =>
Int -> m (MutablePrimArray (PrimState m) a)
newPrimArray Int
siz
            IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (BotanStructT -> MBA# CInt -> Int -> IO CInt
hs_botan_mp_to_bin BotanStructT
bts MBA# CInt
mba# Int
0)
            (PrimArray ByteArray#
ba# :: PrimArray Word8) <- MutablePrimArray (PrimState IO) Word8 -> IO (PrimArray Word8)
forall (m :: * -> *) a.
PrimMonad m =>
MutablePrimArray (PrimState m) a -> m (PrimArray a)
unsafeFreezePrimArray MutablePrimArray RealWorld Word8
MutablePrimArray (PrimState IO) Word8
mpa
            let r :: Integer
r = ByteArray# -> Word# -> Word# -> Int# -> Integer
importIntegerFromByteArray ByteArray#
ba# Word#
0## (Int# -> Word#
int2Word# Int#
siz#) Int#
1#
            Integer -> IO Integer
forall (m :: * -> *) a. Monad m => a -> m a
return (Integer -> IO Integer) -> Integer -> IO Integer
forall a b. (a -> b) -> a -> b
$! if MPI
mp MPI -> MPI -> Bool
forall a. Ord a => a -> a -> Bool
< MPI
0 then Integer -> Integer
forall a. Num a => a -> a
negate Integer
r else Integer
r
      where
        !siz :: Int
siz@(I# Int#
siz#) = (MPI -> Int
byteSize MPI
mp)

-- | The 'testBit' implementation ignore sign.
instance Bits MPI where
    MPI
x .&. :: MPI -> MPI -> MPI
.&. MPI
y = Integer -> MPI
forall a. Num a => Integer -> a
fromInteger (Integer -> MPI) -> Integer -> MPI
forall a b. (a -> b) -> a -> b
$ (MPI -> Integer
forall a. Integral a => a -> Integer
toInteger MPI
x) Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
.&. (MPI -> Integer
forall a. Integral a => a -> Integer
toInteger MPI
y)
    {-# INLINE (.&.) #-}
    MPI
x .|. :: MPI -> MPI -> MPI
.|. MPI
y = Integer -> MPI
forall a. Num a => Integer -> a
fromInteger (Integer -> MPI) -> Integer -> MPI
forall a b. (a -> b) -> a -> b
$ (MPI -> Integer
forall a. Integral a => a -> Integer
toInteger MPI
x) Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
.|. (MPI -> Integer
forall a. Integral a => a -> Integer
toInteger MPI
y)
    {-# INLINE (.|.) #-}
    MPI
x xor :: MPI -> MPI -> MPI
`xor` MPI
y = Integer -> MPI
forall a. Num a => Integer -> a
fromInteger (Integer -> MPI) -> Integer -> MPI
forall a b. (a -> b) -> a -> b
$ (MPI -> Integer
forall a. Integral a => a -> Integer
toInteger MPI
x) Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
`xor` (MPI -> Integer
forall a. Integral a => a -> Integer
toInteger MPI
y)
    {-# INLINE xor #-}
    complement :: MPI -> MPI
complement = Integer -> MPI
forall a. Num a => Integer -> a
fromInteger (Integer -> MPI) -> (MPI -> Integer) -> MPI -> MPI
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Integer
forall a. Bits a => a -> a
complement (Integer -> Integer) -> (MPI -> Integer) -> MPI -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MPI -> Integer
forall a. Integral a => a -> Integer
toInteger
    {-# INLINE complement #-}
    shift :: MPI -> Int -> MPI
shift MPI
x Int
i
        | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 =
            MPI -> (BotanStructT -> IO MPI) -> MPI
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
x ((BotanStructT -> IO MPI) -> MPI)
-> (BotanStructT -> IO MPI) -> MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsx ->
                (BotanStructT -> IO CInt) -> IO MPI
forall a. (BotanStructT -> IO a) -> IO MPI
newMPI ((BotanStructT -> IO CInt) -> IO MPI)
-> (BotanStructT -> IO CInt) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsr ->
                    BotanStructT -> BotanStructT -> CSize -> IO CInt
botan_mp_lshift BotanStructT
btsr BotanStructT
btsx (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i)
        | Bool
otherwise =
            MPI -> (BotanStructT -> IO MPI) -> MPI
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
x ((BotanStructT -> IO MPI) -> MPI)
-> (BotanStructT -> IO MPI) -> MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsx ->
                (BotanStructT -> IO CInt) -> IO MPI
forall a. (BotanStructT -> IO a) -> IO MPI
newMPI ((BotanStructT -> IO CInt) -> IO MPI)
-> (BotanStructT -> IO CInt) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsr ->
                    BotanStructT -> BotanStructT -> CSize -> IO CInt
botan_mp_rshift BotanStructT
btsr BotanStructT
btsx (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral (-Int
i))
    {-# INLINE shift #-}

    testBit :: MPI -> Int -> Bool
testBit MPI
x Int
i =
        MPI -> (BotanStructT -> IO Bool) -> Bool
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
x ((BotanStructT -> IO Bool) -> Bool)
-> (BotanStructT -> IO Bool) -> Bool
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsx -> do
            CInt
r <- BotanStructT -> CSize -> IO CInt
botan_mp_get_bit BotanStructT
btsx (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i)
            Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$! CInt
r CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1
    {-# INLINE testBit #-}

    zeroBits :: MPI
zeroBits   = MPI
0
    bit :: Int -> MPI
bit = MPI -> Int -> MPI
forall a. Bits a => a -> Int -> a
setBit MPI
0
    {-# INLINE bit #-}

    setBit :: MPI -> Int -> MPI
setBit MPI
a Int
i =
        MPI -> (BotanStructT -> IO MPI) -> MPI
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
a ((BotanStructT -> IO MPI) -> MPI)
-> (BotanStructT -> IO MPI) -> MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsa ->
            (BotanStructT -> IO CInt) -> IO MPI
forall a. (BotanStructT -> IO a) -> IO MPI
newMPI (\ BotanStructT
btsr -> do
                IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (BotanStructT -> BotanStructT -> IO CInt
botan_mp_set_from_mp BotanStructT
btsr BotanStructT
btsa)
                BotanStructT -> CSize -> IO CInt
botan_mp_set_bit BotanStructT
btsr (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i))
    {-# INLINE setBit #-}

    clearBit :: MPI -> Int -> MPI
clearBit MPI
a Int
i =
        MPI -> (BotanStructT -> IO MPI) -> MPI
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
a ((BotanStructT -> IO MPI) -> MPI)
-> (BotanStructT -> IO MPI) -> MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsa ->
            (BotanStructT -> IO CInt) -> IO MPI
forall a. (BotanStructT -> IO a) -> IO MPI
newMPI (\ BotanStructT
btsr -> do
                IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (BotanStructT -> BotanStructT -> IO CInt
botan_mp_set_from_mp BotanStructT
btsr BotanStructT
btsa)
                BotanStructT -> CSize -> IO CInt
botan_mp_clear_bit BotanStructT
btsr (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i))
    {-# INLINE clearBit #-}

    popCount :: MPI -> Int
popCount = Integer -> Int
forall a. Bits a => a -> Int
popCount (Integer -> Int) -> (MPI -> Integer) -> MPI -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MPI -> Integer
forall a. Integral a => a -> Integer
toInteger
    {-# INLINE popCount #-}

    rotate :: MPI -> Int -> MPI
rotate MPI
x Int
i = MPI -> Int -> MPI
forall a. Bits a => a -> Int -> a
shift MPI
x Int
i   -- since an MPI never wraps around
    {-# INLINE rotate #-}

    bitSizeMaybe :: MPI -> Maybe Int
bitSizeMaybe MPI
_ = Maybe Int
forall a. Maybe a
Nothing
    bitSize :: MPI -> Int
bitSize MPI
_  = [Char] -> Int
forall a. HasCallStack => [Char] -> a
error [Char]
"Z.Crypto.MPI.bitSize(MPI)"
    isSigned :: MPI -> Bool
isSigned MPI
_ = Bool
True

instance Show MPI where
    show :: MPI -> [Char]
show = MPI -> [Char]
forall a. Print a => a -> [Char]
T.toString

instance T.Print MPI where
    {-# INLINE toUTF8BuilderP #-}
    toUTF8BuilderP :: Int -> MPI -> Builder ()
toUTF8BuilderP Int
_  = MPI -> Builder ()
toDecimal

zero :: MPI
zero :: MPI
zero = (BotanStructT -> IO ()) -> MPI
forall a. (BotanStructT -> IO a) -> MPI
unsafeNewMPI (\ BotanStructT
_ -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ())

newMPI :: (BotanStructT -> IO a) -> IO MPI
{-# INLINABLE newMPI #-}
newMPI :: (BotanStructT -> IO a) -> IO MPI
newMPI BotanStructT -> IO a
f = do
    BotanStruct
mp <- (MBA# CInt -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# CInt -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct (\ MBA# CInt
bts -> MBA# CInt -> IO CInt
botan_mp_init MBA# CInt
bts) FunPtr (BotanStructT -> IO ())
botan_mp_destroy
    a
_ <- BotanStruct -> (BotanStructT -> IO a) -> IO a
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
mp BotanStructT -> IO a
f
    MPI -> IO MPI
forall (m :: * -> *) a. Monad m => a -> m a
return (BotanStruct -> MPI
MPI BotanStruct
mp)

newMPI' :: (BotanStructT -> IO a) -> IO (MPI, a)
{-# INLINABLE newMPI' #-}
newMPI' :: (BotanStructT -> IO a) -> IO (MPI, a)
newMPI' BotanStructT -> IO a
f = do
    BotanStruct
mp <- (MBA# CInt -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# CInt -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct (\ MBA# CInt
bts -> MBA# CInt -> IO CInt
botan_mp_init MBA# CInt
bts) FunPtr (BotanStructT -> IO ())
botan_mp_destroy
    a
r <- BotanStruct -> (BotanStructT -> IO a) -> IO a
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
mp BotanStructT -> IO a
f
    (MPI, a) -> IO (MPI, a)
forall (m :: * -> *) a. Monad m => a -> m a
return (BotanStruct -> MPI
MPI BotanStruct
mp, a
r)

copyMPI :: MPI -> IO MPI
{-# INLINABLE copyMPI #-}
copyMPI :: MPI -> IO MPI
copyMPI (MPI BotanStruct
a) = do
    BotanStruct -> (BotanStructT -> IO MPI) -> IO MPI
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
a ((BotanStructT -> IO MPI) -> IO MPI)
-> (BotanStructT -> IO MPI) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsa -> do
        (BotanStructT -> IO CInt) -> IO MPI
forall a. (BotanStructT -> IO a) -> IO MPI
newMPI (\ BotanStructT
bts -> BotanStructT -> BotanStructT -> IO CInt
botan_mp_set_from_mp BotanStructT
bts BotanStructT
btsa)

withMPI :: MPI -> (BotanStructT -> IO a) -> IO a
{-# INLINABLE withMPI #-}
withMPI :: MPI -> (BotanStructT -> IO a) -> IO a
withMPI (MPI BotanStruct
bts) BotanStructT -> IO a
f = BotanStruct -> (BotanStructT -> IO a) -> IO a
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
bts BotanStructT -> IO a
f

unsafeWithMPI :: MPI -> (BotanStructT -> IO a) -> a
{-# INLINABLE unsafeWithMPI #-}
unsafeWithMPI :: MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI (MPI BotanStruct
bts) BotanStructT -> IO a
f = IO a -> a
forall a. IO a -> a
unsafeDupablePerformIO (BotanStruct -> (BotanStructT -> IO a) -> IO a
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
bts BotanStructT -> IO a
f)

unsafeNewMPI :: (BotanStructT -> IO a) -> MPI
{-# INLINABLE unsafeNewMPI #-}
unsafeNewMPI :: (BotanStructT -> IO a) -> MPI
unsafeNewMPI BotanStructT -> IO a
f = IO MPI -> MPI
forall a. IO a -> a
unsafeDupablePerformIO (IO MPI -> MPI) -> IO MPI -> MPI
forall a b. (a -> b) -> a -> b
$ do
    BotanStruct
mp <- (MBA# CInt -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# CInt -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct (\ MBA# CInt
bts -> MBA# CInt -> IO CInt
botan_mp_init MBA# CInt
bts) FunPtr (BotanStructT -> IO ())
botan_mp_destroy
    a
_ <- BotanStruct -> (BotanStructT -> IO a) -> IO a
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
mp BotanStructT -> IO a
f
    MPI -> IO MPI
forall (m :: * -> *) a. Monad m => a -> m a
return (BotanStruct -> MPI
MPI BotanStruct
mp)

unsafeNewMPI' :: (BotanStructT -> IO a) -> (MPI, a)
{-# INLINABLE unsafeNewMPI' #-}
unsafeNewMPI' :: (BotanStructT -> IO a) -> (MPI, a)
unsafeNewMPI' BotanStructT -> IO a
f = IO (MPI, a) -> (MPI, a)
forall a. IO a -> a
unsafeDupablePerformIO (IO (MPI, a) -> (MPI, a)) -> IO (MPI, a) -> (MPI, a)
forall a b. (a -> b) -> a -> b
$ do
    BotanStruct
mp <- (MBA# CInt -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# CInt -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct (\ MBA# CInt
bts -> MBA# CInt -> IO CInt
botan_mp_init MBA# CInt
bts) FunPtr (BotanStructT -> IO ())
botan_mp_destroy
    a
r <- BotanStruct -> (BotanStructT -> IO a) -> IO a
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
mp BotanStructT -> IO a
f
    (MPI, a) -> IO (MPI, a)
forall (m :: * -> *) a. Monad m => a -> m a
return (BotanStruct -> MPI
MPI BotanStruct
mp, a
r)

-- | Get 'MPI' 's byte size.
byteSize :: MPI -> Int
{-# INLINABLE byteSize #-}
byteSize :: MPI -> Int
byteSize MPI
mp = forall b. (Integral CSize, Num b) => CSize -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral @CSize (CSize -> Int)
-> ((BotanStructT -> IO (CSize, CInt)) -> CSize)
-> (BotanStructT -> IO (CSize, CInt))
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CSize, CInt) -> CSize
forall a b. (a, b) -> a
fst ((CSize, CInt) -> CSize)
-> ((BotanStructT -> IO (CSize, CInt)) -> (CSize, CInt))
-> (BotanStructT -> IO (CSize, CInt))
-> CSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MPI -> (BotanStructT -> IO (CSize, CInt)) -> (CSize, CInt)
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
mp ((BotanStructT -> IO (CSize, CInt)) -> Int)
-> (BotanStructT -> IO (CSize, CInt)) -> Int
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts ->
    (MBA# CInt -> IO CInt) -> IO (CSize, CInt)
forall a b. Prim a => (MBA# CInt -> IO b) -> IO (a, b)
allocPrimUnsafe (BotanStructT -> MBA# CInt -> IO CInt
botan_mp_num_bytes BotanStructT
bts)

-- | Get 'MPI' 's bit size.
bitSize :: MPI -> Int
{-# INLINABLE bitSize #-}
bitSize :: MPI -> Int
bitSize MPI
mp = forall b. (Integral CSize, Num b) => CSize -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral @CSize (CSize -> Int)
-> ((BotanStructT -> IO (CSize, CInt)) -> CSize)
-> (BotanStructT -> IO (CSize, CInt))
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CSize, CInt) -> CSize
forall a b. (a, b) -> a
fst ((CSize, CInt) -> CSize)
-> ((BotanStructT -> IO (CSize, CInt)) -> (CSize, CInt))
-> (BotanStructT -> IO (CSize, CInt))
-> CSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MPI -> (BotanStructT -> IO (CSize, CInt)) -> (CSize, CInt)
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
mp ((BotanStructT -> IO (CSize, CInt)) -> Int)
-> (BotanStructT -> IO (CSize, CInt)) -> Int
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts ->
    (MBA# CInt -> IO CInt) -> IO (CSize, CInt)
forall a b. Prim a => (MBA# CInt -> IO b) -> IO (a, b)
allocPrimUnsafe (BotanStructT -> MBA# CInt -> IO CInt
botan_mp_num_bits BotanStructT
bts)

-- | Set 'MPI' from an integer value.
fromCInt :: CInt -> MPI
{-# INLINABLE fromCInt #-}
fromCInt :: CInt -> MPI
fromCInt CInt
x = (BotanStructT -> IO CInt) -> MPI
forall a. (BotanStructT -> IO a) -> MPI
unsafeNewMPI ((BotanStructT -> IO CInt) -> MPI)
-> (BotanStructT -> IO CInt) -> MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts ->
    BotanStructT -> CInt -> IO CInt
botan_mp_set_from_int BotanStructT
bts CInt
x

-- | Convert a MPI to 'Word32', the sign is ignored.
toWord32 :: MPI -> Word32
{-# INLINABLE toWord32 #-}
toWord32 :: MPI -> Word32
toWord32 MPI
mp = (Word32, CInt) -> Word32
forall a b. (a, b) -> a
fst ((Word32, CInt) -> Word32)
-> ((BotanStructT -> IO (Word32, CInt)) -> (Word32, CInt))
-> (BotanStructT -> IO (Word32, CInt))
-> Word32
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MPI -> (BotanStructT -> IO (Word32, CInt)) -> (Word32, CInt)
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
mp ((BotanStructT -> IO (Word32, CInt)) -> Word32)
-> (BotanStructT -> IO (Word32, CInt)) -> Word32
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts ->
    (MBA# CInt -> IO CInt) -> IO (Word32, CInt)
forall a b. Prim a => (MBA# CInt -> IO b) -> IO (a, b)
allocPrimUnsafe (BotanStructT -> MBA# CInt -> IO CInt
botan_mp_to_uint32 BotanStructT
bts)

-- | Write a 'MPI' in decimal format, with negative sign if < 0.
toDecimal :: MPI -> B.Builder ()
{-# INLINABLE toDecimal #-}
toDecimal :: MPI -> Builder ()
toDecimal MPI
mp = do
    Bool -> Builder () -> Builder ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (MPI -> Bool
isNegative MPI
mp) (Word8 -> Builder ()
B.word8 Word8
MINUS)
    -- botan write \NUL terminator
    Int
-> (MutablePrimArray RealWorld Word8 -> Int -> IO Int)
-> Builder ()
B.ensureN (MPI -> Int
byteSize MPI
mp Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) ((MutablePrimArray RealWorld Word8 -> Int -> IO Int) -> Builder ())
-> (MutablePrimArray RealWorld Word8 -> Int -> IO Int)
-> Builder ()
forall a b. (a -> b) -> a -> b
$ \ (MutablePrimArray MBA# CInt
mba#) Int
off ->
        MPI -> (BotanStructT -> IO Int) -> IO Int
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
mp ((BotanStructT -> IO Int) -> IO Int)
-> (BotanStructT -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btst -> do
            BotanStructT -> MBA# CInt -> Int -> IO Int
hs_botan_mp_to_dec BotanStructT
btst MBA# CInt
mba# Int
off

-- | Parse a 'MPI' in decimal format, parse leading minus sign.
fromDecimal :: P.Parser MPI
{-# INLINABLE fromDecimal #-}
fromDecimal :: Parser MPI
fromDecimal = do
    Word8
sign <- Parser Word8
P.peek
    let neg :: Bool
neg = Word8
sign Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
MINUS
    Bool -> Parser () -> Parser ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
neg Parser ()
P.skipWord8
    v :: Bytes
v@(V.PrimVector (A.PrimArray ByteArray#
ba#) Int
s Int
l) <- (Word8 -> Bool) -> Parser Bytes
P.takeWhile1 Word8 -> Bool
isDigit
    let (MPI
x, CInt
r) = (BotanStructT -> IO CInt) -> (MPI, CInt)
forall a. (BotanStructT -> IO a) -> (MPI, a)
unsafeNewMPI' ((BotanStructT -> IO CInt) -> (MPI, CInt))
-> (BotanStructT -> IO CInt) -> (MPI, CInt)
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts -> do
            CInt
r' <- BotanStructT -> ByteArray# -> Int -> Int -> IO CInt
hs_botan_mp_set_from_dec BotanStructT
bts ByteArray#
ba# Int
s Int
l
            Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
r' CInt -> CInt -> Bool
forall a. Ord a => a -> a -> Bool
>= CInt
0 Bool -> Bool -> Bool
&& Bool
neg) (IO CInt -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$ BotanStructT -> IO CInt
botan_mp_flip_sign BotanStructT
bts)
            CInt -> IO CInt
forall (m :: * -> *) a. Monad m => a -> m a
return CInt
r'
    if (CInt
r CInt -> CInt -> Bool
forall a. Ord a => a -> a -> Bool
< CInt
0)
    then Text -> Parser MPI
forall a. Text -> Parser a
P.fail' (Text -> Parser MPI) -> Text -> Parser MPI
forall a b. (a -> b) -> a -> b
$ Text
"wrong decimal integer: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Bytes -> Text
forall a. Print a => a -> Text
T.toText Bytes
v
    else MPI -> Parser MPI
forall (m :: * -> *) a. Monad m => a -> m a
return MPI
x

-- | Write a 'MPI' in hexadecimal format(without '0x' prefix), the sign is ignored.
toHex :: MPI -> B.Builder ()
{-# INLINABLE toHex #-}
toHex :: MPI -> Builder ()
toHex MPI
mp =
    -- botan write \NUL terminator
    let !siz :: Int
siz = MPI -> Int
byteSize MPI
mp Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
1
    in Int
-> (MutablePrimArray RealWorld Word8 -> Int -> IO Int)
-> Builder ()
B.ensureN (Int
siz Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) ((MutablePrimArray RealWorld Word8 -> Int -> IO Int) -> Builder ())
-> (MutablePrimArray RealWorld Word8 -> Int -> IO Int)
-> Builder ()
forall a b. (a -> b) -> a -> b
$ \ (MutablePrimArray MBA# CInt
mba#) Int
off ->
        MPI -> (BotanStructT -> IO Int) -> IO Int
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
mp ((BotanStructT -> IO Int) -> IO Int)
-> (BotanStructT -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btst -> do
            CInt
_ <- BotanStructT -> MBA# CInt -> Int -> IO CInt
hs_botan_mp_to_hex BotanStructT
btst MBA# CInt
mba# Int
off
            Int -> IO Int
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
offInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
siz)

-- | Parse a 'MPI' in hexadecimal format(without '0x' prefix), no sign is allowed.
fromHex :: P.Parser MPI
{-# INLINABLE fromHex #-}
fromHex :: Parser MPI
fromHex = do
    v :: Bytes
v@(V.PrimVector (A.PrimArray ByteArray#
ba#) Int
s Int
l) <- (Word8 -> Bool) -> Parser Bytes
P.takeWhile1 Word8 -> Bool
isHexDigit
    let (MPI
x, CInt
r) = (BotanStructT -> IO CInt) -> (MPI, CInt)
forall a. (BotanStructT -> IO a) -> (MPI, a)
unsafeNewMPI' ((BotanStructT -> IO CInt) -> (MPI, CInt))
-> (BotanStructT -> IO CInt) -> (MPI, CInt)
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts -> BotanStructT -> ByteArray# -> Int -> Int -> IO CInt
hs_botan_mp_set_from_hex BotanStructT
bts ByteArray#
ba# Int
s Int
l
    if (CInt
r CInt -> CInt -> Bool
forall a. Ord a => a -> a -> Bool
< CInt
0)
    then Text -> Parser MPI
forall a. Text -> Parser a
P.fail' (Text -> Parser MPI) -> Text -> Parser MPI
forall a b. (a -> b) -> a -> b
$ Text
"wrong hexadecimal integer: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Bytes -> Text
forall a. Print a => a -> Text
T.toText Bytes
v
    else MPI -> Parser MPI
forall (m :: * -> *) a. Monad m => a -> m a
return MPI
x

isNegative :: MPI -> Bool
{-# INLINABLE isNegative #-}
isNegative :: MPI -> Bool
isNegative MPI
mp = MPI -> (BotanStructT -> IO Bool) -> Bool
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
mp ((BotanStructT -> IO Bool) -> Bool)
-> (BotanStructT -> IO Bool) -> Bool
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts -> do
    CInt
r <- BotanStructT -> IO CInt
botan_mp_is_negative BotanStructT
bts
    Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$! CInt
r CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1

isZero :: MPI -> Bool
{-# INLINABLE isZero #-}
isZero :: MPI -> Bool
isZero MPI
mp = MPI -> (BotanStructT -> IO Bool) -> Bool
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
mp ((BotanStructT -> IO Bool) -> Bool)
-> (BotanStructT -> IO Bool) -> Bool
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts -> do
    CInt
r <- BotanStructT -> IO CInt
botan_mp_is_zero BotanStructT
bts
    Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$! CInt
r CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1

isOdd :: MPI -> Bool
{-# INLINABLE isOdd #-}
isOdd :: MPI -> Bool
isOdd MPI
mp = MPI -> (BotanStructT -> IO Bool) -> Bool
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
mp ((BotanStructT -> IO Bool) -> Bool)
-> (BotanStructT -> IO Bool) -> Bool
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts -> do
    CInt
r <- BotanStructT -> IO CInt
botan_mp_is_odd BotanStructT
bts
    Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$! CInt
r CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1

isEven :: MPI -> Bool
{-# INLINABLE isEven #-}
isEven :: MPI -> Bool
isEven MPI
mp = MPI -> (BotanStructT -> IO Bool) -> Bool
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
mp ((BotanStructT -> IO Bool) -> Bool)
-> (BotanStructT -> IO Bool) -> Bool
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts -> do
    CInt
r <- BotanStructT -> IO CInt
botan_mp_is_even BotanStructT
bts
    Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$! CInt
r CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1

--------------------------------------------------------------------------------

-- | mulMod x y mod = x times y modulo mod
mulMod :: MPI -> MPI -> MPI -> MPI
{-# INLINABLE mulMod #-}
mulMod :: MPI -> MPI -> MPI -> MPI
mulMod MPI
x MPI
y MPI
m =
    (BotanStructT -> IO CInt) -> MPI
forall a. (BotanStructT -> IO a) -> MPI
unsafeNewMPI ((BotanStructT -> IO CInt) -> MPI)
-> (BotanStructT -> IO CInt) -> MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsr ->
        MPI -> (BotanStructT -> IO CInt) -> IO CInt
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
x ((BotanStructT -> IO CInt) -> IO CInt)
-> (BotanStructT -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsx ->
            MPI -> (BotanStructT -> IO CInt) -> IO CInt
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
y ((BotanStructT -> IO CInt) -> IO CInt)
-> (BotanStructT -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsy ->
                MPI -> (BotanStructT -> IO CInt) -> IO CInt
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
m ((BotanStructT -> IO CInt) -> IO CInt)
-> (BotanStructT -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsm ->
                    BotanStructT
-> BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_mp_mod_mul BotanStructT
btsr BotanStructT
btsx BotanStructT
btsy BotanStructT
btsm


-- | Modular exponentiation. powMod base exp mod = base power exp module mod
powMod :: MPI -> MPI -> MPI -> MPI
{-# INLINABLE powMod #-}
powMod :: MPI -> MPI -> MPI -> MPI
powMod MPI
x MPI
y MPI
m =
    (BotanStructT -> IO CInt) -> MPI
forall a. (BotanStructT -> IO a) -> MPI
unsafeNewMPI ((BotanStructT -> IO CInt) -> MPI)
-> (BotanStructT -> IO CInt) -> MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsr ->
        MPI -> (BotanStructT -> IO CInt) -> IO CInt
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
x ((BotanStructT -> IO CInt) -> IO CInt)
-> (BotanStructT -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsx ->
            MPI -> (BotanStructT -> IO CInt) -> IO CInt
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
y ((BotanStructT -> IO CInt) -> IO CInt)
-> (BotanStructT -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsy ->
                MPI -> (BotanStructT -> IO CInt) -> IO CInt
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
m ((BotanStructT -> IO CInt) -> IO CInt)
-> (BotanStructT -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsm ->
                    BotanStructT
-> BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_mp_powmod BotanStructT
btsr BotanStructT
btsx BotanStructT
btsy BotanStructT
btsm

-- | Modular inverse, find an integer x so that @a⋅x ≡ 1  mod m@
--
-- If no modular inverse exists (for instance because in and modulus are not relatively prime), return 0.
modInverse :: MPI -> MPI -> MPI
{-# INLINABLE modInverse #-}
modInverse :: MPI -> MPI -> MPI
modInverse MPI
x MPI
y =
    (BotanStructT -> IO CInt) -> MPI
forall a. (BotanStructT -> IO a) -> MPI
unsafeNewMPI ((BotanStructT -> IO CInt) -> MPI)
-> (BotanStructT -> IO CInt) -> MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsr ->
        MPI -> (BotanStructT -> IO CInt) -> IO CInt
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
x ((BotanStructT -> IO CInt) -> IO CInt)
-> (BotanStructT -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsx ->
            MPI -> (BotanStructT -> IO CInt) -> IO CInt
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
y ((BotanStructT -> IO CInt) -> IO CInt)
-> (BotanStructT -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
btsy ->
                    BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_mp_mod_inverse BotanStructT
btsr BotanStructT
btsx BotanStructT
btsy

-- | Create a random 'MPI' of the specified bit size.
randBits :: HasCallStack => RNG -> Int -> IO MPI
{-# INLINABLE randBits #-}
randBits :: RNG -> Int -> IO MPI
randBits RNG
rng Int
x = do
    (BotanStructT -> IO ()) -> IO MPI
forall a. (BotanStructT -> IO a) -> IO MPI
newMPI ((BotanStructT -> IO ()) -> IO MPI)
-> (BotanStructT -> IO ()) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts ->
        RNG -> (BotanStructT -> IO ()) -> IO ()
forall a. RNG -> (BotanStructT -> IO a) -> IO a
withRNG RNG
rng ((BotanStructT -> IO ()) -> IO ())
-> (BotanStructT -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts_rng ->
            IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (BotanStructT -> BotanStructT -> CSize -> IO CInt
botan_mp_rand_bits BotanStructT
bts BotanStructT
bts_rng (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
x Int
0)))

-- | Create a random 'MPI' within the provided range.
randRange :: HasCallStack
          => RNG
          -> MPI     -- ^ lower bound
          -> MPI     -- ^ upper bound
          -> IO MPI
{-# INLINABLE randRange #-}
randRange :: RNG -> MPI -> MPI -> IO MPI
randRange RNG
rng MPI
lower MPI
upper = do
    (BotanStructT -> IO ()) -> IO MPI
forall a. (BotanStructT -> IO a) -> IO MPI
newMPI ((BotanStructT -> IO ()) -> IO MPI)
-> (BotanStructT -> IO ()) -> IO MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts ->
        RNG -> (BotanStructT -> IO ()) -> IO ()
forall a. RNG -> (BotanStructT -> IO a) -> IO a
withRNG RNG
rng ((BotanStructT -> IO ()) -> IO ())
-> (BotanStructT -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts_rng ->
            MPI -> (BotanStructT -> IO ()) -> IO ()
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
lower ((BotanStructT -> IO ()) -> IO ())
-> (BotanStructT -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts_lower ->
                MPI -> (BotanStructT -> IO ()) -> IO ()
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
upper ((BotanStructT -> IO ()) -> IO ())
-> (BotanStructT -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts_upper ->
                    IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (BotanStructT
-> BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_mp_rand_range BotanStructT
bts BotanStructT
bts_rng BotanStructT
bts_lower BotanStructT
bts_upper)

-- | Compute the greatest common divisor of x and y.
gcd :: MPI -> MPI -> MPI
{-# INLINABLE gcd #-}
gcd :: MPI -> MPI -> MPI
gcd MPI
x MPI
y = (BotanStructT -> IO CInt) -> MPI
forall a. (BotanStructT -> IO a) -> MPI
unsafeNewMPI ((BotanStructT -> IO CInt) -> MPI)
-> (BotanStructT -> IO CInt) -> MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts ->
    MPI -> (BotanStructT -> IO CInt) -> IO CInt
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
x ((BotanStructT -> IO CInt) -> IO CInt)
-> (BotanStructT -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts_x ->
        MPI -> (BotanStructT -> IO CInt) -> IO CInt
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
y ((BotanStructT -> IO CInt) -> IO CInt)
-> (BotanStructT -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts_y ->
            BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_mp_gcd BotanStructT
bts BotanStructT
bts_x BotanStructT
bts_y

-- | Test if n is prime.
--
-- The algorithm used (Miller-Rabin) is probabilistic,
-- set test_prob to the desired assurance level.
-- For example if test_prob is 64, then sufficient Miller-Rabin iterations will run to
-- assure there is at most a 1/2**64 chance that n is composite.
isPrim :: HasCallStack => RNG -> MPI -> Int -> IO Bool
{-# INLINABLE isPrim #-}
isPrim :: RNG -> MPI -> Int -> IO Bool
isPrim RNG
rng MPI
x Int
prob = do
    RNG -> (BotanStructT -> IO Bool) -> IO Bool
forall a. RNG -> (BotanStructT -> IO a) -> IO a
withRNG RNG
rng ((BotanStructT -> IO Bool) -> IO Bool)
-> (BotanStructT -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts_rng ->
        MPI -> (BotanStructT -> IO Bool) -> IO Bool
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
x ((BotanStructT -> IO Bool) -> IO Bool)
-> (BotanStructT -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
bts_x -> do
            CInt
r <- IO CInt -> IO CInt
forall a. (HasCallStack, Integral a) => IO a -> IO a
throwBotanIfMinus (BotanStructT -> BotanStructT -> CSize -> IO CInt
botan_mp_is_prime BotanStructT
bts_x BotanStructT
bts_rng
                (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 Int
prob)))
            Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$! CInt
r CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1