Support modular division of signed numbers.

This commit is contained in:
2018-12-23 21:55:07 -08:00
parent 2480bafe06
commit ae8266885b
66 changed files with 221461 additions and 1 deletions

View File

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

View File

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

View File

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

View File

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