Support modular division of signed numbers.
This commit is contained in:
@@ -102,6 +102,7 @@ main = do
|
||||
SignedMul -> hPutStrLn hndl ("mul_impls!(I" ++ show size ++ ", I" ++ show (size * 2) ++ ");")
|
||||
SignedDiv -> hPutStrLn hndl ("div_impls!(I" ++ show size ++ ", U" ++ show size ++ ");")
|
||||
EGCD -> hPutStrLn hndl ("egcd_impls!(I" ++ show (size + 64) ++ ", U" ++ show size ++ ", I" ++ show size ++ ");")
|
||||
ModDiv -> hPutStrLn hndl ("moddiv_impls!(I" ++ show size ++ ", I" ++ show (size * 2) ++ ");")
|
||||
ModInv -> hPutStrLn hndl ("modinv_impls!(U" ++ show size ++ ", I" ++ show (size + 64) ++ ", U" ++ show (size + 64) ++ ");")
|
||||
SigConvert v -> hPutStrLn hndl ("conversion_impls!(I" ++ show size ++ ", U" ++ show size ++ ", I" ++ show v ++ ", U" ++ show v ++ ");")
|
||||
_ -> return ()
|
||||
@@ -118,5 +119,6 @@ main = do
|
||||
generateSigTestBlock hndl "sigshiftl" SignedShift True 16384 [] []
|
||||
generateSigTestBlock hndl "sigshiftr" SignedShift True 16384 [] []
|
||||
generateSigTestBlock hndl "egcd" EGCD True 1024 [(+ 64)] [(+ 64)]
|
||||
generateSigTestBlock hndl "moddiv" ModDiv True 2048 [] []
|
||||
generateSigTestBlock hndl "modinv" ModInv True 2048 [] []
|
||||
hPutStrLn hndl "}"
|
||||
|
||||
@@ -4,11 +4,13 @@ module Math(
|
||||
, barrett, computeK, base
|
||||
, modulate, modulate'
|
||||
, isqrt
|
||||
, divmod
|
||||
, showX, showB
|
||||
)
|
||||
where
|
||||
|
||||
import Data.Bits(shiftL,shiftR)
|
||||
import GHC.Integer.GMP.Internals(recipModInteger)
|
||||
import Numeric(showHex)
|
||||
|
||||
data AlgState = AlgState {
|
||||
@@ -122,6 +124,13 @@ isqrt bits val = final
|
||||
| num >= (res + bit) = (num - (res + bit), res + (bit `shiftL` 1))
|
||||
| otherwise = (num, res)
|
||||
|
||||
divmod :: Integer -> Integer -> Integer -> Maybe Integer
|
||||
divmod x y m =
|
||||
let y' = y `mod` m
|
||||
in case recipModInteger y' m of
|
||||
0 -> Nothing
|
||||
i -> Just ((x * i) `mod` m)
|
||||
|
||||
_run :: Integer -> Integer -> IO ()
|
||||
_run inputx inputy =
|
||||
do let (x, y, g, initState) = initialState inputx inputy 1
|
||||
|
||||
@@ -11,6 +11,7 @@ data Operation = Add
|
||||
| BaseOps
|
||||
| Barretts
|
||||
| Div
|
||||
| ModDiv
|
||||
| ModExp
|
||||
| ModMul
|
||||
| ModSq
|
||||
@@ -64,6 +65,7 @@ needs = [ Need RSA (\ size -> [Req (size `div` 2) Sub,
|
||||
Req size (Convert (((size * 2) + 64) * 2))
|
||||
])
|
||||
, Need ECDSA (\ size -> [Req size SignedSub,
|
||||
Req size ModDiv,
|
||||
Req (size + 64) SignedMul,
|
||||
Req ((size + 64) * 2) SignedSub,
|
||||
Req ((size + 64) * 2) SignedDiv,
|
||||
@@ -117,6 +119,12 @@ needs = [ Need RSA (\ size -> [Req (size `div` 2) Sub,
|
||||
Req size Mul,
|
||||
Req size (Convert (size + 64))
|
||||
])
|
||||
, Need ModDiv (\ size -> [Req size ModInv,
|
||||
Req size SignedMul,
|
||||
Req size SignedDiv,
|
||||
Req (size * 2) SignedDiv,
|
||||
Req size (SigConvert (size * 2))
|
||||
])
|
||||
, Need ModSq (\ size -> [Req size BaseOps,
|
||||
Req (size * 2) BaseOps,
|
||||
Req size Barretts,
|
||||
@@ -160,7 +168,8 @@ needs = [ Need RSA (\ size -> [Req (size `div` 2) Sub,
|
||||
Req (size * 2) SignedBase,
|
||||
Req size (SigConvert (size * 2))
|
||||
])
|
||||
, Need SignedDiv (\ size -> [Req size Div
|
||||
, Need SignedDiv (\ size -> [Req size Div,
|
||||
Req size Add
|
||||
])
|
||||
, Need EGCD (\ size -> [Req size SignedBase,
|
||||
Req size BaseOps,
|
||||
|
||||
@@ -43,6 +43,7 @@ testDatabase = [
|
||||
(SignedSub, "sigsub", "signed subtraction", sigsubTest),
|
||||
(SquareRoot, "sqrt", "square root", sqrtTest),
|
||||
(EGCD, "egcd", "EGCD", egcdTest),
|
||||
(ModDiv, "moddiv", "modular division", moddivTest),
|
||||
(ModInv, "modinv", "modular inversion", modinvTest)
|
||||
]
|
||||
|
||||
@@ -278,6 +279,22 @@ egcdTest size memory0 =
|
||||
("v", showX v)]
|
||||
in assert (v == gcd x y) (res, v, memory2)
|
||||
|
||||
moddivTest :: Test
|
||||
moddivTest size memoryIn =
|
||||
let attempt memory0 =
|
||||
let (a, memory1) = genSign (generateNum memory0 "a" size)
|
||||
(b, memory2) = generateNum memory1 "b" size
|
||||
(m, memory3) = generateNum memory2 "m" size
|
||||
maybe_res = divmod a b m
|
||||
in case maybe_res of
|
||||
Nothing ->
|
||||
attempt memory3
|
||||
Just c ->
|
||||
let res = Map.fromList [("a", showX a), ("b", showX b),
|
||||
("m", showX m), ("c", showX c)]
|
||||
in (res, c, memory3)
|
||||
in attempt memoryIn
|
||||
|
||||
modinvTest :: Test
|
||||
modinvTest size memoryIn =
|
||||
let attempt memory0 =
|
||||
|
||||
Reference in New Issue
Block a user