[number] further push the compat cleanup
This commit is contained in:
parent
8c07305deb
commit
228f1ab938
@ -1,9 +1,5 @@
|
|||||||
{-# LANGUAGE BangPatterns #-}
|
{-# LANGUAGE BangPatterns #-}
|
||||||
{-# LANGUAGE DeriveDataTypeable #-}
|
{-# LANGUAGE DeriveDataTypeable #-}
|
||||||
{-# LANGUAGE CPP #-}
|
|
||||||
#ifndef MIN_VERSION_integer_gmp
|
|
||||||
#define MIN_VERSION_integer_gmp(a,b,c) 0
|
|
||||||
#endif
|
|
||||||
-- |
|
-- |
|
||||||
-- Module : Crypto.Number.ModArithmetic
|
-- Module : Crypto.Number.ModArithmetic
|
||||||
-- License : BSD-style
|
-- License : BSD-style
|
||||||
@ -16,11 +12,6 @@ module Crypto.Number.ModArithmetic
|
|||||||
-- * exponentiation
|
-- * exponentiation
|
||||||
expSafe
|
expSafe
|
||||||
, expFast
|
, expFast
|
||||||
, exponentiation_rtl_binary
|
|
||||||
, exponentiation
|
|
||||||
-- * deprecated name for exponentiation
|
|
||||||
, exponantiation_rtl_binary
|
|
||||||
, exponantiation
|
|
||||||
-- * inverse computing
|
-- * inverse computing
|
||||||
, inverse
|
, inverse
|
||||||
, inverseCoprimes
|
, inverseCoprimes
|
||||||
@ -28,13 +19,8 @@ module Crypto.Number.ModArithmetic
|
|||||||
|
|
||||||
import Control.Exception (throw, Exception)
|
import Control.Exception (throw, Exception)
|
||||||
import Data.Typeable
|
import Data.Typeable
|
||||||
|
import Crypto.Number.Basic
|
||||||
#if MIN_VERSION_integer_gmp(0,5,1)
|
import Crypto.Number.Compat
|
||||||
import GHC.Integer.GMP.Internals
|
|
||||||
#else
|
|
||||||
import Crypto.Number.Basic (gcde)
|
|
||||||
import Data.Bits
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-- | Raised when two numbers are supposed to be coprimes but are not.
|
-- | Raised when two numbers are supposed to be coprimes but are not.
|
||||||
data CoprimesAssertionError = CoprimesAssertionError
|
data CoprimesAssertionError = CoprimesAssertionError
|
||||||
@ -59,15 +45,12 @@ expSafe :: Integer -- ^ base
|
|||||||
-> Integer -- ^ exponant
|
-> Integer -- ^ exponant
|
||||||
-> Integer -- ^ modulo
|
-> Integer -- ^ modulo
|
||||||
-> Integer -- ^ result
|
-> Integer -- ^ result
|
||||||
#if MIN_VERSION_integer_gmp(0,5,1)
|
|
||||||
expSafe b e m
|
expSafe b e m
|
||||||
#if !(MIN_VERSION_integer_gmp(1,0,0))
|
| odd m = gmpPowModSecInteger b e m `onGmpUnsupported`
|
||||||
| odd m = powModSecInteger b e m
|
(gmpPowModInteger b e m `onGmpUnsupported`
|
||||||
#endif
|
exponentiation b e m)
|
||||||
| otherwise = powModInteger b e m
|
| otherwise = gmpPowModInteger b e m `onGmpUnsupported`
|
||||||
#else
|
exponentiation b e m
|
||||||
expSafe = exponentiation
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-- | Compute the modular exponentiation of base^exponant using
|
-- | Compute the modular exponentiation of base^exponant using
|
||||||
-- the fastest algorithm without any consideration for
|
-- the fastest algorithm without any consideration for
|
||||||
@ -79,36 +62,11 @@ expFast :: Integer -- ^ base
|
|||||||
-> Integer -- ^ exponant
|
-> Integer -- ^ exponant
|
||||||
-> Integer -- ^ modulo
|
-> Integer -- ^ modulo
|
||||||
-> Integer -- ^ result
|
-> Integer -- ^ result
|
||||||
expFast =
|
expFast b e m = gmpPowModInteger b e m `onGmpUnsupported` exponentiation b e m
|
||||||
#if MIN_VERSION_integer_gmp(0,5,1)
|
|
||||||
powModInteger
|
|
||||||
#else
|
|
||||||
exponentiation
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-- note on exponentiation: 0^0 is treated as 1 for mimicking the standard library;
|
|
||||||
-- the mathematic debate is still open on whether or not this is true, but pratically
|
|
||||||
-- in computer science it shouldn't be useful for anything anyway.
|
|
||||||
|
|
||||||
-- | exponentiation_rtl_binary computes modular exponentiation as b^e mod m
|
|
||||||
-- using the right-to-left binary exponentiation algorithm (HAC 14.79)
|
|
||||||
exponentiation_rtl_binary :: Integer -> Integer -> Integer -> Integer
|
|
||||||
#if MIN_VERSION_integer_gmp(0,5,1)
|
|
||||||
exponentiation_rtl_binary = expSafe
|
|
||||||
#else
|
|
||||||
exponentiation_rtl_binary 0 0 m = 1 `mod` m
|
|
||||||
exponentiation_rtl_binary b e m = loop e b 1
|
|
||||||
where sq x = (x * x) `mod` m
|
|
||||||
loop !0 _ !a = a `mod` m
|
|
||||||
loop !i !s !a = loop (i `shiftR` 1) (sq s) (if odd i then a * s else a)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-- | exponentiation computes modular exponentiation as b^e mod m
|
-- | exponentiation computes modular exponentiation as b^e mod m
|
||||||
-- using repetitive squaring.
|
-- using repetitive squaring.
|
||||||
exponentiation :: Integer -> Integer -> Integer -> Integer
|
exponentiation :: Integer -> Integer -> Integer -> Integer
|
||||||
#if MIN_VERSION_integer_gmp(0,5,1)
|
|
||||||
exponentiation = expSafe
|
|
||||||
#else
|
|
||||||
exponentiation b e m
|
exponentiation b e m
|
||||||
| b == 1 = b
|
| b == 1 = b
|
||||||
| e == 0 = 1
|
| e == 0 = 1
|
||||||
@ -116,29 +74,15 @@ exponentiation b e m
|
|||||||
| even e = let p = (exponentiation b (e `div` 2) m) `mod` m
|
| even e = let p = (exponentiation b (e `div` 2) m) `mod` m
|
||||||
in (p^(2::Integer)) `mod` m
|
in (p^(2::Integer)) `mod` m
|
||||||
| otherwise = (b * exponentiation b (e-1) m) `mod` m
|
| otherwise = (b * exponentiation b (e-1) m) `mod` m
|
||||||
#endif
|
|
||||||
|
|
||||||
--{-# DEPRECATED exponantiation_rtl_binary "typo in API name it's called exponentiation_rtl_binary #-}
|
|
||||||
exponantiation_rtl_binary :: Integer -> Integer -> Integer -> Integer
|
|
||||||
exponantiation_rtl_binary = exponentiation_rtl_binary
|
|
||||||
|
|
||||||
--{-# DEPRECATED exponentiation "typo in API name it's called exponentiation #-}
|
|
||||||
exponantiation :: Integer -> Integer -> Integer -> Integer
|
|
||||||
exponantiation = exponentiation
|
|
||||||
|
|
||||||
-- | inverse computes the modular inverse as in g^(-1) mod m
|
-- | inverse computes the modular inverse as in g^(-1) mod m
|
||||||
inverse :: Integer -> Integer -> Maybe Integer
|
inverse :: Integer -> Integer -> Maybe Integer
|
||||||
#if MIN_VERSION_integer_gmp(0,5,1)
|
inverse g m = gmpInverse g m `onGmpUnsupported` v
|
||||||
inverse g m
|
where
|
||||||
| r == 0 = Nothing
|
v
|
||||||
| otherwise = Just r
|
| d > 1 = Nothing
|
||||||
where r = recipModInteger g m
|
| otherwise = Just (x `mod` m)
|
||||||
#else
|
(x,_,d) = gcde g m
|
||||||
inverse g m
|
|
||||||
| d > 1 = Nothing
|
|
||||||
| otherwise = Just (x `mod` m)
|
|
||||||
where (x,_,d) = gcde g m
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-- | Compute the modular inverse of 2 coprime numbers.
|
-- | Compute the modular inverse of 2 coprime numbers.
|
||||||
-- This is equivalent to inverse except that the result
|
-- This is equivalent to inverse except that the result
|
||||||
|
|||||||
@ -24,7 +24,7 @@ import Crypto.Internal.Imports
|
|||||||
import Crypto.Number.Compat
|
import Crypto.Number.Compat
|
||||||
import Crypto.Number.Generate
|
import Crypto.Number.Generate
|
||||||
import Crypto.Number.Basic (sqrti, gcde)
|
import Crypto.Number.Basic (sqrti, gcde)
|
||||||
import Crypto.Number.ModArithmetic (exponantiation)
|
import Crypto.Number.ModArithmetic (expSafe)
|
||||||
import Crypto.Random.Types
|
import Crypto.Random.Types
|
||||||
|
|
||||||
import Data.Bits
|
import Data.Bits
|
||||||
@ -107,7 +107,7 @@ primalityTestMillerRabin tries !n =
|
|||||||
factorise !si !vi
|
factorise !si !vi
|
||||||
| vi `testBit` 0 = (si, vi)
|
| vi `testBit` 0 = (si, vi)
|
||||||
| otherwise = factorise (si+1) (vi `shiftR` 1) -- probably faster to not shift v continously, but just once.
|
| otherwise = factorise (si+1) (vi `shiftR` 1) -- probably faster to not shift v continously, but just once.
|
||||||
expmod = exponantiation
|
expmod = expSafe
|
||||||
|
|
||||||
-- when iteration reach zero, we have a probable prime
|
-- when iteration reach zero, we have a probable prime
|
||||||
loop [] = True
|
loop [] = True
|
||||||
@ -142,7 +142,7 @@ primalityTestFermat :: Int -- ^ number of iterations of the algorithm
|
|||||||
-> Bool
|
-> Bool
|
||||||
primalityTestFermat n a p = and $ map expTest [a..(a+fromIntegral n)]
|
primalityTestFermat n a p = and $ map expTest [a..(a+fromIntegral n)]
|
||||||
where !pm1 = p-1
|
where !pm1 = p-1
|
||||||
expTest i = exponantiation i pm1 p == 1
|
expTest i = expSafe i pm1 p == 1
|
||||||
|
|
||||||
-- | Test naively is integer is prime.
|
-- | Test naively is integer is prime.
|
||||||
-- while naive, we skip even number and stop iteration at i > sqrt(n)
|
-- while naive, we skip even number and stop iteration at i > sqrt(n)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user