[number] further push the compat cleanup

This commit is contained in:
Vincent Hanquez 2015-05-11 07:32:13 +01:00
parent 8c07305deb
commit 228f1ab938
2 changed files with 17 additions and 73 deletions

View File

@ -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

View File

@ -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)