Base implementation of signed numbers and EGCD, with tests.

This commit is contained in:
2018-10-15 19:16:25 -07:00
parent d43f0bcd42
commit 89e2dfc6ef
164 changed files with 560116 additions and 67 deletions

View File

@@ -1,8 +1,10 @@
{-# LANGUAGE RecordWildCards #-}
import Control.Exception(assert)
import Control.Monad(foldM_,forM_,when)
import Data.Bits(shiftL,shiftR)
import Data.List(sort)
import qualified Data.Map.Strict as Map
import GHC.Integer.GMP.Internals(powModInteger)
import GHC.Integer.GMP.Internals(powModInteger,recipModInteger)
import Numeric(showHex)
import Prelude hiding (log)
import System.Directory(createDirectoryIfMissing)
@@ -11,6 +13,8 @@ import System.FilePath((</>))
import System.IO(Handle,IOMode(WriteMode),hPutStrLn,withFile,hFlush,hPutStr,stderr)
import System.Random(StdGen,newStdGen,random,split)
import Debug.Trace
data Operation = Add
| BaseOps
| Barretts
@@ -23,6 +27,14 @@ data Operation = Add
| Square
| Sub
| Convert Int
| SignedAdd
| SignedBase
| SignedCmp
| SignedShift
| SignedSub
| SigConvert Int
| EGCD
| ModInv
deriving (Eq, Ord, Show)
data Requirement = Req Int Operation
@@ -31,44 +43,64 @@ data Requirement = Req Int Operation
data Need = Need Operation (Int -> [Requirement])
needs :: [Need]
needs = [ Need ModExp (\ size -> [Req size ModMul
,Req size ModSq
,Req size Barretts])
, Need ModSq (\ size -> [Req (size * 2) Div
,Req size Barretts
,Req size Square])
, Need ModMul (\ size -> [Req size Mul
,Req size Barretts
,Req size (Convert (size * 2))
,Req (size * 2) Div])
, Need Barretts (\ size -> [Req (size + 64) BaseOps
,Req size (Convert (size + 64))
,Req (size + 64) (Convert ((size * 2) + 64))
,Req size (Convert ((size * 2) + 64))
,Req ((size * 2) + 64) Add
,Req ((size * 2) + 64) Sub
,Req (size + 64) Mul
,Req (size * 2) (Convert ((size * 2) + 64))
,Req ((size * 2) + 64) Shifts
,Req ((size * 2) + 128) Shifts
,Req ((size * 2) + 64) Div
,Req (size + 64) (Convert (size * 2))
,Req (size + 64) (Convert ((size * 2) + 128))
,Req ((size * 2) + 64)
(Convert ((size * 2) + 128))
])
, Need Div (\ size -> [Req size (Convert (size * 2))
,Req 192 BaseOps
,Req 384 BaseOps
,Req 192 Mul
,Req size Mul
,Req size Shifts
,Req (size * 2) Sub
])
, Need Mul (\ size -> [Req (size * 2) BaseOps])
, Need Sub (\ size -> [Req size Add])
, Need Add (\ size -> [Req (size + 64) BaseOps
,Req size (Convert (size + 64))])
needs = [ Need ModExp (\ size -> [Req size ModMul
,Req size ModSq
,Req size Barretts])
, Need ModSq (\ size -> [Req (size * 2) Div
,Req size Barretts
,Req size Square])
, Need ModMul (\ size -> [Req size Mul
,Req size Barretts
,Req size (Convert (size * 2))
,Req (size * 2) Div])
, Need Barretts (\ size -> [Req (size + 64) BaseOps
,Req size (Convert (size + 64))
,Req (size + 64) (Convert ((size * 2) + 64))
,Req size (Convert ((size * 2) + 64))
,Req ((size * 2) + 64) Add
,Req ((size * 2) + 64) Sub
,Req (size + 64) Mul
,Req (size * 2) (Convert ((size * 2) + 64))
,Req ((size * 2) + 64) Shifts
,Req ((size * 2) + 128) Shifts
,Req ((size * 2) + 64) Div
,Req (size + 64) (Convert (size * 2))
,Req (size + 64) (Convert ((size * 2) + 128))
,Req ((size * 2) + 64)
(Convert ((size * 2) + 128))
])
, Need Div (\ size -> [Req size (Convert (size * 2))
,Req 192 BaseOps
,Req 384 BaseOps
,Req 192 Mul
,Req size Mul
,Req size Shifts
,Req (size * 2) Sub
])
, Need Mul (\ size -> [Req (size * 2) BaseOps])
, Need Sub (\ size -> [Req size Add])
, Need Add (\ size -> [Req (size + 64) BaseOps
,Req size (Convert (size + 64))])
, Need ModInv (\ size -> [Req size SignedBase,
Req size EGCD])
, Need EGCD (\ size -> [Req size BaseOps,
Req (size + 64) SignedBase,
Req size (SigConvert (size + 64)),
Req (size + 64) SignedShift,
Req (size + 64) SignedAdd,
Req (size + 64) SignedSub,
Req (size + 64) SignedCmp
])
, Need SignedShift (\ size -> [Req size Shifts, Req size Add])
, Need SignedAdd (\ size -> [Req size Sub,
Req (size + 64) Add,
Req (size + 64) SignedBase,
Req size (SigConvert (size + 64))
])
, Need SignedSub (\ size -> [Req (size + 64) SignedBase,
Req size (SigConvert (size + 64)),
Req size Sub
])
]
newRequirements :: Requirement -> [Requirement]
@@ -81,7 +113,7 @@ bitSizes :: [Int]
bitSizes = [192,256,384,512,576,1024,2048,3072,4096,7680,8192,15360]
baseRequirements :: [Requirement]
baseRequirements = map (\ x -> Req x ModExp) bitSizes
baseRequirements = concatMap (\ x -> [Req x ModExp, Req x ModInv]) bitSizes
requirements :: [Requirement]
requirements = go baseRequirements
@@ -123,8 +155,31 @@ generateTestBlock hndl name level useRT ignoreAt addOns =
");")
hPutStrLn hndl " }"
generateSigTestBlock :: Handle ->
String -> Operation -> Bool -> Int ->
[Int -> Int] -> [Int -> Int] ->
IO ()
generateSigTestBlock hndl name level useRT ignoreAt addOns uaddOns =
do hPutStrLn hndl (" mod " ++ name ++ " {")
when useRT $
do hPutStrLn hndl (" use super::super::*;")
hPutStrLn hndl (" use testing::run_test;")
hPutStrLn hndl ""
forM_ requirements $ \ (Req size kind) ->
when (kind == level) $
hPutStrLn hndl (" generate_" ++ name ++
"_tests!(" ++
(if size >= ignoreAt then "ignore " else "") ++
"I" ++ show size ++ ", " ++
"U" ++ show size ++ ", " ++
"i" ++ show size ++
concatMap (\ f -> ", I" ++ show (f size)) addOns ++
concatMap (\ f -> ", U" ++ show (f size)) uaddOns ++
");")
hPutStrLn hndl " }"
generateInvocs :: IO ()
generateInvocs =
generateInvocs = do
withFile "src/unsigned/invoc.rs" WriteMode $ \ hndl ->
do forM_ requirements $ \ (Req size oper) ->
case oper of
@@ -141,6 +196,7 @@ generateInvocs =
Square -> hPutStrLn hndl ("square_impls!(U" ++ show size ++ ", U" ++ show (size * 2) ++ ", " ++ show size ++ ");")
Sub -> hPutStrLn hndl ("subtraction_impls!(U" ++ show size ++ ", " ++ show (size `div` 64) ++ ");")
Convert to -> hPutStrLn hndl ("conversion_impls!(U" ++ show size ++ ", U" ++ show to ++ ");")
_ -> return ()
hPutStrLn hndl ""
hPutStrLn hndl "\n#[cfg(test)]"
hPutStrLn hndl "mod tests {"
@@ -164,18 +220,43 @@ generateInvocs =
generateTestBlock hndl "barrett_modmul" Barretts True 4000 [(+ 64)]
generateTestBlock hndl "barrett_modexp" Barretts True 1024 [(+ 64)]
hPutStrLn hndl "}"
withFile "src/signed/invoc.rs" WriteMode $ \ hndl ->
do forM_ requirements $ \ (Req size oper) ->
case oper of
SignedAdd -> hPutStrLn hndl ("add_impls!(I" ++ show size ++ ", I" ++ show (size + 64) ++ ", U" ++ show (size + 64) ++ ");")
SignedBase -> hPutStrLn hndl ("signed_impls!(I" ++ show size ++ ", U" ++ show size ++ ");")
SignedCmp -> hPutStrLn hndl ("cmp_impls!(I" ++ show size ++ ");")
SignedShift -> hPutStrLn hndl ("shift_impls!(I" ++ show size ++ ", U" ++ show size ++ ");")
SignedSub -> hPutStrLn hndl ("subtraction_impls!(I" ++ show size ++ ", I" ++ show (size + 64) ++ ", U" ++ show (size + 64) ++ ");")
EGCD -> hPutStrLn hndl ("egcd_impls!(I" ++ show (size + 64) ++ ", U" ++ show size ++ ", I" ++ show size ++ ");")
ModInv -> hPutStrLn hndl ("modinv_impls!(I" ++ show size ++ ");")
SigConvert v -> hPutStrLn hndl ("conversion_impls!(I" ++ show size ++ ", U" ++ show size ++ ", I" ++ show v ++ ", U" ++ show v ++ ");")
_ -> return ()
hPutStrLn hndl ""
hPutStrLn hndl "\n#[cfg(test)]"
hPutStrLn hndl "mod tests {"
generateSigTestBlock hndl "sigadd" SignedAdd True 16384 [(+ 64)] [(+ 64)]
generateSigTestBlock hndl "sigsub" SignedSub True 16384 [(+ 64)] [(+ 64)]
generateSigTestBlock hndl "signed" SignedBase True 90000 [] []
generateSigTestBlock hndl "sigconversion" SignedBase False 90000 [] []
generateSigTestBlock hndl "sigcmp" SignedCmp True 90000 [] []
generateSigTestBlock hndl "sigshiftl" SignedShift True 16384 [] []
generateSigTestBlock hndl "sigshiftr" SignedShift True 16384 [] []
generateSigTestBlock hndl "egcd" EGCD True 1024 [(+ 64)] [(+ 64)]
generateSigTestBlock hndl "modinv" ModInv True 9000 [] []
hPutStrLn hndl "}"
log :: String -> IO ()
log str = hPutStr stderr str >> hFlush stderr
generateTests :: Operation -> String -> Database ->
generateTests :: String -> Operation -> String -> Database ->
(Int -> Database -> (Map.Map String String, Integer, Database)) ->
IO ()
generateTests op directory init runner = do
generateTests prefix op directory init runner = do
forM_ (getSizes op requirements) $ \ size ->
do createDirectoryIfMissing True ("testdata" </> directory)
log $ "Generating " ++ show size ++ "-bit " ++ directory ++ " tests: 000%"
let dest = "testdata" </> directory </> ("U" ++ show size ++ ".tests")
let dest = "testdata" </> directory </> (prefix ++ show size ++ ".tests")
withFile dest WriteMode $ \ hndl ->
foldM_ (writer hndl size runner) init [0..numberOfTests]
log "\n"
@@ -216,11 +297,20 @@ generateNum (db, rng0) varname size =
then (x', (Map.insert varname (x':before) db, rng1))
else generateNum (db, rng1) varname size
genSign :: (Integer, Database) -> (Integer, Database)
genSign (x, (db, rng0)) =
let (n, rng1) = random rng0
in if n then (0 - x, (db, rng1)) else (x, (db, rng1))
modulate :: Integer -> Int -> Integer
modulate x size = x `mod` (2 ^ size)
modulate' :: Integer -> Int -> Integer
modulate' x size = signum x * (abs x `mod` (2 ^ size))
showX :: (Integral a, Show a) => a -> String
showX x = showHex x ""
showX x | x < 0 = "-" ++ showX (abs x)
| otherwise = showHex x ""
showB :: Bool -> String
showB False = "0"
@@ -244,7 +334,7 @@ generateAllTheTests :: IO ()
generateAllTheTests =
do gen0 <- newStdGen
let (db1, gen1) = emptyDatabase gen0
generateTests Add "add" db1 $ \ size memory0 ->
generateTests "U" Add "add" db1 $ \ size memory0 ->
let (a, memory1) = generateNum memory0 "a" size
(b, memory2) = generateNum memory1 "b" size
c = a + b
@@ -252,7 +342,7 @@ generateAllTheTests =
("c", showX c)]
in (res, c, memory2)
let (db2, gen2) = emptyDatabase gen1
generateTests Barretts "barrett_gen" db2 $ \ size memory0 ->
generateTests "U" Barretts "barrett_gen" db2 $ \ size memory0 ->
let (m, memory1) = generateNum memory0 "m" size
k = computeK m
u = barrett m
@@ -260,7 +350,7 @@ generateAllTheTests =
("u", showX u)]
in (res, u, memory1)
let (db3, gen3) = emptyDatabase gen2
generateTests Barretts "barrett_reduce" db3 $ \ size memory0 ->
generateTests "U" Barretts "barrett_reduce" db3 $ \ size memory0 ->
let (m, memory1) = generateNum memory0 "m" size
(x, memory2) = generateNum memory1 "x" (min (2 * size) (2 * k * 64))
k = computeK m
@@ -271,7 +361,7 @@ generateAllTheTests =
("r", showX r)]
in (res, r, memory2)
let (db4, gen4) = emptyDatabase gen3
generateTests BaseOps "base" db4 $ \ size memory0 ->
generateTests "U" BaseOps "base" db4 $ \ size memory0 ->
let (x, memory1) = generateNum memory0 "x" size
(m, memory2) = generateNum memory1 "m" size
m' = m `mod` (fromIntegral size `div` 64)
@@ -281,7 +371,7 @@ generateAllTheTests =
("m", showX m'), ("r", showX r)]
in (res, x, memory2)
let (db5, gen5) = emptyDatabase gen4
generateTests BaseOps "cmp" db5 $ \ size memory0 ->
generateTests "U" BaseOps "cmp" db5 $ \ size memory0 ->
let (a, memory1) = generateNum memory0 "a" size
(b, memory2) = generateNum memory1 "b" size
res = Map.fromList [("a", showX a), ("b", showX b),
@@ -289,7 +379,7 @@ generateAllTheTests =
("e", showB (a == b))]
in (res, a, memory2)
let (db6, gen6) = emptyDatabase gen5
generateTests Div "div" db6 $ \ size memory0 ->
generateTests "U" Div "div" db6 $ \ size memory0 ->
let (a, memory1) = generateNum memory0 "a" size
(b, memory2) = generateNum memory1 "b" size
q = a `div` b
@@ -298,7 +388,7 @@ generateAllTheTests =
("q", showX q), ("r", showX r)]
in (res, q, memory2)
let (db7, gen7) = emptyDatabase gen6
generateTests Mul "mul" db7 $ \ size memory0 ->
generateTests "U" Mul "mul" db7 $ \ size memory0 ->
let (a, memory1) = generateNum memory0 "a" size
(b, memory2) = generateNum memory1 "b" size
c = a * b
@@ -306,7 +396,7 @@ generateAllTheTests =
("c", showX c)]
in (res, c, memory2)
let (db8, gen8) = emptyDatabase gen7
generateTests Shifts "shiftl" db8 $ \ size memory0 ->
generateTests "U" Shifts "shiftl" db8 $ \ size memory0 ->
let (a, memory1) = generateNum memory0 "a" size
(l, memory2) = generateNum memory1 "l" size
l' = l `mod` fromIntegral (computeK a * 64)
@@ -314,7 +404,7 @@ generateAllTheTests =
res = Map.fromList [("a", showX a), ("l", showX l'), ("r", showX r)]
in (res, r, memory2)
let (db9, gen9) = emptyDatabase gen8
generateTests Shifts "shiftr" db9 $ \ size memory0 ->
generateTests "U" Shifts "shiftr" db9 $ \ size memory0 ->
let (a, memory1) = generateNum memory0 "a" size
(l, memory2) = generateNum memory1 "l" size
l' = l `mod` fromIntegral (computeK a * 64)
@@ -322,7 +412,7 @@ generateAllTheTests =
res = Map.fromList [("a", showX a), ("l", showX l'), ("r", showX r)]
in (res, l, memory2)
let (dbA, genA) = emptyDatabase gen9
generateTests Sub "sub" dbA $ \ size memory0 ->
generateTests "U" Sub "sub" dbA $ \ size memory0 ->
let (a, memory1) = generateNum memory0 "a" size
(b, memory2) = generateNum memory1 "b" size
c = modulate (a - b) size
@@ -330,7 +420,7 @@ generateAllTheTests =
("c", showX c)]
in (res, c, memory2)
let (dbB, genB) = emptyDatabase genA
generateTests ModSq "modsq" dbB $ \ size memory0 ->
generateTests "U" ModSq "modsq" dbB $ \ size memory0 ->
let (a, memory1) = generateNum memory0 "a" size
(m, memory2) = generateNum memory1 "m" size
k = computeK m
@@ -341,7 +431,7 @@ generateAllTheTests =
("k", showX k)]
in (res, c, memory2)
let (dbC, genC) = emptyDatabase genB
generateTests ModMul "modmul" dbC $ \ size memory0 ->
generateTests "U" ModMul "modmul" dbC $ \ size memory0 ->
let (a, memory1) = generateNum memory0 "a" size
(b, memory2) = generateNum memory1 "b" size
(m, memory3) = generateNum memory2 "m" size
@@ -353,7 +443,7 @@ generateAllTheTests =
("u", showX u), ("k", showX k)]
in (res, c, memory3)
let (dbD, genD) = emptyDatabase genC
generateTests ModExp "modexp" dbD $ \ size memory0 ->
generateTests "U" ModExp "modexp" dbD $ \ size memory0 ->
let (b, memory1) = generateNum memory0 "b" size
(e, memory2) = generateNum memory1 "e" size
(m, memory3) = generateNum memory2 "m" size
@@ -365,11 +455,140 @@ generateAllTheTests =
("u", showX u), ("k", showX k)]
in (res, r, memory3)
let (dbE, genE) = emptyDatabase genD
generateTests Square "square" dbE $ \ size memory0 ->
generateTests "U" Square "square" dbE $ \ size memory0 ->
let (a, memory1) = generateNum memory0 "a" size
r = modulate (a * a) (2 * size)
res = Map.fromList [("a", showX a), ("r", showX r)]
in (res, r, memory1)
--
let (dbF, genF) = emptyDatabase genE
generateTests "I" SignedAdd "sigadd" dbF $ \ size memory0 ->
let (a, memory1) = genSign (generateNum memory0 "a" size)
(b, memory2) = genSign (generateNum memory1 "b" size)
c = a + b
res = Map.fromList [("a", showX a), ("b", showX b),
("c", showX c)]
in (res, c, memory2)
let (dbG, genG) = emptyDatabase genF
generateTests "I" SignedSub "sigsub" dbG $ \ size memory0 ->
let (a, memory1) = genSign (generateNum memory0 "a" size)
(b, memory2) = genSign (generateNum memory1 "b" size)
c = a - b
res = Map.fromList [("a", showX a), ("b", showX b),
("c", showX c)]
in (res, c, memory2)
let (dbH, genH) = emptyDatabase genG
generateTests "I" SignedBase "signed" dbH $ \ size memory0 ->
let (x, memory1) = genSign (generateNum memory0 "x" size)
res = Map.fromList [("x", showX x), ("z", showB (x == 0)),
("e", showB (even x)), ("o", showB (odd x))]
in (res, x, memory1)
let (dbI, genI) = emptyDatabase genH
generateTests "I" SignedShift "sigshiftl" dbI $ \ size memory0 ->
let (a, memory1) = genSign (generateNum memory0 "a" size)
(l, memory2) = generateNum memory1 "l" size
l' = l `mod` fromIntegral (computeK (abs a) * 64)
r = modulate' (a `shiftL` fromIntegral l') size
res = Map.fromList [("a", showX a), ("l", showX l'), ("r", showX r)]
in (res, r, memory2)
let (dbJ, genJ) = emptyDatabase genI
generateTests "I" SignedShift "sigshiftr" dbJ $ \ size memory0 ->
let (a, memory1) = genSign (generateNum memory0 "a" size)
(l, memory2) = generateNum memory1 "l" size
l' = l `mod` fromIntegral (computeK (abs a) * 64)
r = modulate' (a `shiftR` fromIntegral l') size
res = Map.fromList [("a", showX a), ("l", showX l'), ("r", showX r)]
in (res, l, memory2)
let (dbK, genK) = emptyDatabase genJ
generateTests "I" SignedCmp "sigcmp" dbK $ \ size memory0 ->
let (a, memory1) = genSign (generateNum memory0 "a" size)
(b, memory2) = genSign (generateNum memory1 "b" size)
res = Map.fromList [("a", showX a), ("b", showX b),
("g", showB (a > b)), ("l", showB (a < b)),
("e", showB (a == b))]
in (res, a, memory2)
let (dbL, genL) = emptyDatabase genK
generateTests "I" EGCD "egcd" dbL $ \ size memory0 ->
let (x, memory1) = generateNum memory0 "x" size
(y, memory2) = generateNum memory1 "y" size
ans@(a, b, v) = extendedGCD x y
res = Map.fromList [("x", showX x), ("y", showX y),
("a", showX a), ("b", showX b),
("v", showX v)]
in assert (v == gcd x y) (res, v, memory2)
let (dbM, genM) = emptyDatabase genL
generateTests "I" ModInv "modinv" dbM $ \ size memory0 ->
let (a, memory1) = genSign (generateNum memory0 "a" size)
(b, memory2) = genSign (generateNum memory1 "b" size)
c = recipModInteger a b
res = Map.fromList [("a", showX a), ("b", showX b),
("c", showX c)]
in (res, c, memory2)
data AlgState = AlgState {
u :: Integer,
v :: Integer,
bigA :: Integer,
bigB :: Integer,
bigC :: Integer,
bigD :: Integer
}
printState :: AlgState -> IO ()
printState a =
do putStrLn ("u: " ++ showX (u a))
putStrLn ("v: " ++ showX (v a))
putStrLn ("A: " ++ showX (bigA a))
putStrLn ("B: " ++ showX (bigB a))
putStrLn ("C: " ++ showX (bigC a))
putStrLn ("D: " ++ showX (bigD a))
extendedGCD :: Integer -> Integer -> (Integer, Integer, Integer)
extendedGCD x y = (a, b, g * (v finalState))
where
(x', y', g, initState) = initialState x y 1
finalState = runAlgorithm x' y' initState
a = bigC finalState
b = bigD finalState
initialState :: Integer -> Integer -> Integer -> (Integer, Integer, Integer, AlgState)
initialState x y g | even x && even y = initialState (x `div` 2) (y `div` 2) (g * 2)
| otherwise = (x, y, g, AlgState x y 1 0 0 1)
runAlgorithm :: Integer -> Integer -> AlgState -> AlgState
runAlgorithm x y state | u state == 0 = state
| otherwise = runAlgorithm x y state6
where
state4 = step4 x y state
state5 = step5 x y state4
state6 = step6 state5
step4 :: Integer -> Integer -> AlgState -> AlgState
step4 x y input@AlgState{..} | even u = step4 x y input'
| otherwise = input
where
input' = AlgState u' v bigA' bigB' bigC bigD
u' = u `div` 2
bigA' | even bigA && even bigB = bigA `div` 2
| otherwise = (bigA + y) `div` 2
bigB' | even bigA && even bigB = bigB `div` 2
| otherwise = (bigB - x) `div` 2
step5 :: Integer -> Integer -> AlgState -> AlgState
step5 x y input@AlgState{..} | even v = step5 x y input'
| otherwise = input
where
input' = AlgState u v' bigA bigB bigC' bigD'
v' = v `div` 2
bigC' | even bigC && even bigD = bigC `div` 2
| otherwise = (bigC + y) `div` 2
bigD' | even bigC && even bigD = bigD `div` 2
| otherwise = (bigD - x) `div` 2
step6 :: AlgState -> AlgState
step6 input@AlgState{..}
| u >= v = AlgState (u - v) v (bigA - bigC) (bigB - bigD) bigC bigD
| otherwise = AlgState u (v - u) bigA bigB (bigC - bigA) (bigD - bigB)
main :: IO ()
main =
@@ -377,3 +596,31 @@ main =
let args' = if null args then ["invocs", "tests"] else args
when ("invocs" `elem` args') generateInvocs
when ("tests" `elem` args') generateAllTheTests
---
run :: Integer -> Integer -> IO ()
run inputx inputy =
do let (x, y, g, initState) = initialState inputx inputy 1
finalState <- go x y initState
putStrLn ("-- FINAL STATE -----------------------")
printState finalState
putStrLn ("Final value: " ++ showX (g * v finalState))
putStrLn ("-- RUN ------")
printState (runAlgorithm x y initState)
putStrLn ("-- NORMAL ------")
let (a, b, v) = extendedGCD inputx inputy
putStrLn ("a: " ++ showX a)
putStrLn ("b: " ++ showX b)
putStrLn ("v: " ++ showX v)
where
go x y state =
do putStrLn "-- STATE -----------------------------"
printState state
if u state == 0
then return state
else do let state' = step4 x y state
state'' = step5 x y state'
state''' = step6 state''
go x y state'''

View File

@@ -4,6 +4,7 @@
#[macro_use]
extern crate quickcheck;
pub mod signed;
pub mod unsigned;
#[cfg(test)]
pub mod testing;

113
src/signed/add.rs Normal file
View File

@@ -0,0 +1,113 @@
macro_rules! add_impls
{
($name: ident, $bigger: ident, $ubigger: ident) => {
impl AddAssign<$name> for $name {
fn add_assign(&mut self, rhs: $name) {
self.add_assign(&rhs);
}
}
impl<'a> AddAssign<&'a $name> for $name {
fn add_assign(&mut self, rhs: &$name) {
if self.negative == rhs.negative {
unsafe_addition(&mut self.value.value, &rhs.value.value, true);
} else {
if self.value > rhs.value {
self.value -= rhs.value.clone();
} else {
self.value = rhs.value.clone() - self.value.clone();
self.negative = rhs.negative;
}
}
}
}
impl Add<$name> for $name {
type Output = $bigger;
fn add(self, rhs: $name) -> $bigger
{
&self + &rhs
}
}
impl<'a> Add<&'a $name> for $name {
type Output = $bigger;
fn add(self, rhs: &$name) -> $bigger
{
&self + rhs
}
}
impl<'a> Add<$name> for &'a $name {
type Output = $bigger;
fn add(self, rhs: $name) -> $bigger
{
self + &rhs
}
}
impl<'a,'b> Add<&'a $name> for &'b $name {
type Output = $bigger;
fn add(self, rhs: &$name) -> $bigger
{
if self.negative == rhs.negative {
$bigger{
negative: self.negative,
value: &self.value + &rhs.value
}
} else {
if self.value > rhs.value {
$bigger {
negative: self.negative,
value: $ubigger::from(&self.value - &rhs.value)
}
} else {
$bigger {
negative: rhs.negative,
value: $ubigger::from(&rhs.value - &self.value)
}
}
}
}
}
}
}
#[cfg(test)]
macro_rules! generate_sigadd_tests {
($sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
#[test]
fn $lname() {
generate_sigadd_tests!(body$sname, $name, $lname, $bigger, $ubigger);
}
};
(ignore $sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
#[test]
#[ignore]
fn $lname() {
generate_sigadd_tests!(body $sname, $name, $lname, $bigger, $ubigger);
}
};
(body $sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
let fname = format!("testdata/sigadd/{}.tests", stringify!($sname));
run_test(fname.to_string(), 3, |case| {
let (nega, abytes) = case.get("a").unwrap();
let (negb, bbytes) = case.get("b").unwrap();
let (negc, cbytes) = case.get("c").unwrap();
let mut a = $sname::new(*nega, $name::from_bytes(abytes));
let b = $sname::new(*negb, $name::from_bytes(bbytes));
let c = $bigger::new(*negc, $ubigger::from_bytes(cbytes));
assert_eq!(c, &a + &b, "base addition");
if c.value.value[c.value.value.len()-1] == 0 {
a += b;
assert_eq!($sname::from(c), a, "mutating addition");
}
});
};
}

154
src/signed/base.rs Normal file
View File

@@ -0,0 +1,154 @@
macro_rules! signed_impls {
($sname: ident, $name: ident) => {
#[derive(Clone, PartialEq, Eq)]
pub struct $sname {
negative: bool,
value: $name
}
impl $sname {
pub fn new(negative: bool, value: $name) -> $sname {
$sname{ negative: negative, value: value }
}
pub fn negate(&self) -> $sname {
$sname{ negative: !self.negative, value: self.value.clone() }
}
pub fn abs(&self) -> $sname {
$sname{ negative: false, value: self.value.clone() }
}
}
impl From<$sname> for $name {
fn from(x: $sname) -> $name {
x.value
}
}
impl<'a> From<&'a $sname> for $name {
fn from(x: &$sname) -> $name {
x.value.clone()
}
}
impl From<$name> for $sname {
fn from(x: $name) -> $sname {
$sname{ negative: false, value: x }
}
}
impl<'a> From<&'a $name> for $sname {
fn from(x: &$name) -> $sname {
$sname{ negative: false, value: x.clone() }
}
}
impl CryptoNum for $sname {
fn zero() -> $sname {
$sname{ negative: false, value: $name::zero() }
}
fn is_zero(&self) -> bool {
self.value.is_zero()
}
fn is_even(&self) -> bool {
self.value.is_even()
}
fn is_odd(&self) -> bool {
self.value.is_odd()
}
fn mask(&mut self, len: usize) {
self.value.mask(len);
}
}
// #[cfg(test)]
// impl Arbitrary for $sname {
// fn arbitrary<G: Gen>(g: &mut G) -> $name {
// let neg = g.gen::<bool>();
// let val = g.gen::<$name>();
// $sname{ negative: neg, value: val }
// }
// }
#[cfg(test)]
impl fmt::Debug for $sname {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.negative {
f.write_str("-")?;
}
self.value.fmt(f)
}
}
impl fmt::UpperHex for $sname {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.negative {
write!(f, "-{:X}", self.value)
} else {
if f.sign_plus() {
write!(f, "+{:X}", self.value)
} else {
write!(f, "{:X}", self.value)
}
}
}
}
impl fmt::LowerHex for $sname {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.negative {
write!(f, "-{:x}", self.value)
} else {
if f.sign_plus() {
write!(f, "+{:x}", self.value)
} else {
write!(f, "{:x}", self.value)
}
}
}
}
generate_base_conversions!($sname, $name);
};
}
#[cfg(test)]
macro_rules! generate_signed_tests
{
($sname: ident, $name: ident, $lname: ident) => {
#[test]
fn $lname() {
generate_signed_tests!(body $sname, $name, $lname);
}
};
(ignore $sname: ident, $name: ident, $lname: ident) => {
#[test]
#[ignore]
fn $lname() {
generate_signed_tests!(body $sname, $name, $lname);
}
};
(body $sname: ident, $name: ident, $lname: ident) => {
let fname = format!("testdata/signed/{}.tests", stringify!($sname));
run_test(fname.to_string(), 4, |case| {
let (negx, xbytes) = case.get("x").unwrap();
let (neg0, zbytes) = case.get("z").unwrap();
let (neg1, ebytes) = case.get("e").unwrap();
let (neg2, obytes) = case.get("o").unwrap();
assert!(!neg0 && !neg1 && !neg2);
let x = $sname::new(*negx, $name::from_bytes(xbytes));
let z = 1 == zbytes[0];
let e = 1 == ebytes[0];
let o = 1 == obytes[0];
assert_eq!(x.is_zero(), z);
assert_eq!(x.is_even(), e);
assert_eq!(x.is_odd(), o);
});
}
}

61
src/signed/compare.rs Normal file
View File

@@ -0,0 +1,61 @@
macro_rules! cmp_impls {
($name: ident) => {
impl PartialOrd for $name {
fn partial_cmp(&self, rhs: &$name) -> Option<Ordering> {
Some(self.cmp(&rhs))
}
}
impl Ord for $name {
fn cmp(&self, rhs: &$name) -> Ordering {
match (self.negative, rhs.negative) {
(false, false) => self.value.cmp(&rhs.value),
(true, false) => Ordering::Less,
(false, true) => Ordering::Greater,
(true, true) => self.value.cmp(&rhs.value).reverse()
}
}
}
}
}
#[cfg(test)]
macro_rules! generate_sigcmp_tests {
($sname: ident, $name: ident, $lname: ident) => {
#[test]
fn $lname() {
generate_sigcmp_tests!(body $sname, $name, $lname);
}
};
(ignore $sname: ident, $name: ident, $lname: ident) => {
#[test]
#[ignore]
fn $lname() {
generate_sigcmp_tests!(body $sname, $name, $lname);
}
};
(body $sname: ident, $name: ident, $lname: ident) => {
let fname = format!("testdata/sigcmp/{}.tests", stringify!($sname));
run_test(fname.to_string(), 5, |case| {
let (nega, abytes) = case.get("a").unwrap();
let (negb, bbytes) = case.get("b").unwrap();
let (neg2, ebytes) = case.get("e").unwrap();
let (neg3, gbytes) = case.get("g").unwrap();
let (neg4, lbytes) = case.get("l").unwrap();
assert!(!neg2 && !neg3 && !neg4);
let a = $sname::new(*nega, $name::from_bytes(abytes));
let b = $sname::new(*negb, $name::from_bytes(bbytes));
let e = 1 == ebytes[0];
let g = 1 == gbytes[0];
let l = 1 == lbytes[0];
assert_eq!(e, a == b, "equals wrong");
assert_eq!(g, a > b, "greater than wrong");
assert_eq!(l, a < b, "less than wrong");
assert_eq!(e || g, a >= b, "greater / equals wrong");
assert_eq!(e || l, a <= b, "less than / equals wrong");
});
};
}

99
src/signed/conversion.rs Normal file
View File

@@ -0,0 +1,99 @@
macro_rules! generate_base_conversions
{
($sname: ident, $name: ident) => {
generate_base_type_convert!($sname, $name, i8, u8);
generate_base_type_convert!($sname, $name, i16, u16);
generate_base_type_convert!($sname, $name, i32, u32);
generate_base_type_convert!($sname, $name, i64, u64);
generate_base_type_convert!($sname, $name, isize, usize);
impl From<i128> for $sname {
fn from(x: i128) -> $sname {
$sname{ negative: x < 0, value: $name::from(x.abs() as u128) }
}
}
};
}
macro_rules! generate_base_type_convert
{
($sname: ident, $name: ident, $sbase: ident, $base: ident) => {
impl From<$sbase> for $sname {
fn from(x: $sbase) -> $sname {
$sname {
negative: x < 0,
value: $name::from(x.abs() as $base)
}
}
}
impl From<$sname> for $sbase {
fn from(x: $sname) -> $sbase {
let signum = if x.negative { -1 } else { 1 };
signum * ($base::from(x.value) as $sbase)
}
}
impl<'a> From<&'a $sname> for $sbase {
fn from(x: &$sname) -> $sbase {
let signum = if x.negative { -1 } else { 1 };
signum * ($base::from(&x.value) as $sbase)
}
}
}
}
#[cfg(test)]
macro_rules! generate_sigconversion_tests
{
($sname: ident, $name: ident, $lname: ident) => {
#[cfg(test)]
mod $lname {
use super::super::super::*;
use std::convert::From;
quickcheck! {
fn conversion_i8( x: i8) -> bool { x == i8::from($sname::from(x)) }
fn conversion_i16( x: i16) -> bool { x == i16::from($sname::from(x)) }
fn conversion_i32( x: i32) -> bool { x == i32::from($sname::from(x)) }
fn conversion_i64( x: i64) -> bool { x == i64::from($sname::from(x)) }
fn conversion_isize(x: isize) -> bool { x == isize::from($sname::from(x)) }
}
}
}
}
macro_rules! conversion_impls
{
($sname: ident, $name: ident, $sother: ident, $other: ident) => {
impl<'a> From<&'a $sother> for $sname {
fn from(x: &$sother) -> $sname {
$sname {
negative: x.negative,
value: $name::from(&x.value)
}
}
}
impl<'a> From<&'a $sname> for $sother {
fn from(x: &$sname) -> $sother {
$sother {
negative: x.negative,
value: $other::from(&x.value)
}
}
}
impl From<$sother> for $sname {
fn from(x: $sother) -> $sname {
$sname::from(&x)
}
}
impl From<$sname> for $sother {
fn from(x: $sname) -> $sother {
$sother::from(&x)
}
}
};
}

125
src/signed/egcd.rs Normal file
View File

@@ -0,0 +1,125 @@
pub trait EGCD<T> {
fn egcd(&self, rhs: &Self) -> (T, T, T);
}
macro_rules! egcd_impls {
($sname: ident, $name: ident, $ssmall: ident) => {
impl EGCD<$sname> for $name {
fn egcd(&self, rhs: &$name) -> ($sname, $sname, $sname) {
// INPUT: two positive integers x and y.
let mut x = $sname::from($ssmall::from(self));
let mut y = $sname::from($ssmall::from(rhs));
// OUTPUT: integers a, b, and v such that ax + by = v,
// where v = gcd(x, y).
// 1. g←1.
let mut gshift = 0;
// 2. While x and y are both even, do the following: x←x/2,
// y←y/2, g←2g.
while x.is_even() && y.is_even() {
x >>= 1;
y >>= 1;
gshift += 1;
}
// 3. u←x, v←y, A←1, B←0, C←0, D←1.
let mut u = x.clone();
let mut v = y.clone();
#[allow(non_snake_case)]
let mut A = $sname::from(1i64);
#[allow(non_snake_case)]
let mut B = $sname::zero();
#[allow(non_snake_case)]
let mut C = $sname::zero();
#[allow(non_snake_case)]
let mut D = $sname::from(1i64);
loop {
// 4. While u is even do the following:
while u.is_even() {
// 4.1 u←u/2.
u >>= 1;
// 4.2 If A≡B≡0 (mod 2) then A←A/2, B←B/2; otherwise,
// A←(A + y)/2, B←(B x)/2.
if A.is_even() && B.is_even() {
A >>= 1;
B >>= 1;
} else {
A += &y;
A >>= 1;
B -= &x;
B >>= 1;
}
}
// 5. While v is even do the following:
while v.is_even() {
// 5.1 v←v/2.
v >>= 1;
// 5.2 If C ≡ D ≡ 0 (mod 2) then C←C/2, D←D/2; otherwise,
// C←(C + y)/2, D←(D x)/2.
if C.is_even() && D.is_even() {
C >>= 1;
D >>= 1;
} else {
C += &y;
C >>= 1;
D -= &x;
D >>= 1;
}
}
// 6. If u≥v then u←uv, A←AC,B←BD;
// otherwise,v←vu, C←CA, D←DB.
if u >= v {
u -= &v;
A -= &C;
B -= &D;
} else {
v -= &u;
C -= &A;
D -= &B;
}
// 7. If u = 0, then a←C, b←D, and return(a, b, g · v);
// otherwise, go to step 4.
if u.is_zero() {
return (C, D, v << gshift);
}
}
}
}
};
}
#[cfg(test)]
macro_rules! generate_egcd_tests {
($sname: ident, $uname: ident, $tname: ident, $sname64: ident, $uname64: ident) => {
#[test]
fn $tname() {
generate_egcd_tests!(body $sname, $uname, $tname, $sname64, $uname64);
}
};
(ignore $sname: ident, $uname: ident, $tname: ident, $sname64: ident, $uname64: ident) => {
#[test]
#[ignore]
fn $tname() {
generate_egcd_tests!(body $sname, $uname, $tname, $sname64, $uname64);
}
};
(body $sname: ident, $uname: ident, $tname: ident, $sname64: ident, $uname64: ident) => {
let fname = format!("testdata/egcd/{}.tests", stringify!($sname));
run_test(fname.to_string(), 5, |case| {
let (negx, xbytes) = case.get("x").unwrap();
let (negy, ybytes) = case.get("y").unwrap();
let (negv, vbytes) = case.get("v").unwrap();
let (nega, abytes) = case.get("a").unwrap();
let (negb, bbytes) = case.get("b").unwrap();
assert!(!negx && !negy);
let x = $uname::from_bytes(xbytes);
let y = $uname::from_bytes(ybytes);
let v = $sname64::new(*negv, $uname64::from_bytes(vbytes));
let a = $sname64::new(*nega, $uname64::from_bytes(abytes));
let b = $sname64::new(*negb, $uname64::from_bytes(bbytes));
let (mya, myb, myv) = x.egcd(&y);
assert_eq!(v, myv, "GCD test");
assert_eq!(a, mya, "X factor test");
assert_eq!(b, myb, "Y factor tst");
});
};
}

315
src/signed/invoc.rs Normal file
View File

@@ -0,0 +1,315 @@
signed_impls!(I192, U192);
conversion_impls!(I192, U192, I256, U256);
egcd_impls!(I256, U192, I192);
modinv_impls!(I192);
add_impls!(I256, I320, U320);
signed_impls!(I256, U256);
cmp_impls!(I256);
shift_impls!(I256, U256);
subtraction_impls!(I256, I320, U320);
conversion_impls!(I256, U256, I320, U320);
egcd_impls!(I320, U256, I256);
modinv_impls!(I256);
add_impls!(I320, I384, U384);
signed_impls!(I320, U320);
cmp_impls!(I320);
shift_impls!(I320, U320);
subtraction_impls!(I320, I384, U384);
conversion_impls!(I320, U320, I384, U384);
signed_impls!(I384, U384);
conversion_impls!(I384, U384, I448, U448);
egcd_impls!(I448, U384, I384);
modinv_impls!(I384);
add_impls!(I448, I512, U512);
signed_impls!(I448, U448);
cmp_impls!(I448);
shift_impls!(I448, U448);
subtraction_impls!(I448, I512, U512);
conversion_impls!(I448, U448, I512, U512);
signed_impls!(I512, U512);
conversion_impls!(I512, U512, I576, U576);
egcd_impls!(I576, U512, I512);
modinv_impls!(I512);
add_impls!(I576, I640, U640);
signed_impls!(I576, U576);
cmp_impls!(I576);
shift_impls!(I576, U576);
subtraction_impls!(I576, I640, U640);
conversion_impls!(I576, U576, I640, U640);
egcd_impls!(I640, U576, I576);
modinv_impls!(I576);
add_impls!(I640, I704, U704);
signed_impls!(I640, U640);
cmp_impls!(I640);
shift_impls!(I640, U640);
subtraction_impls!(I640, I704, U704);
conversion_impls!(I640, U640, I704, U704);
signed_impls!(I704, U704);
signed_impls!(I1024, U1024);
conversion_impls!(I1024, U1024, I1088, U1088);
egcd_impls!(I1088, U1024, I1024);
modinv_impls!(I1024);
add_impls!(I1088, I1152, U1152);
signed_impls!(I1088, U1088);
cmp_impls!(I1088);
shift_impls!(I1088, U1088);
subtraction_impls!(I1088, I1152, U1152);
conversion_impls!(I1088, U1088, I1152, U1152);
signed_impls!(I1152, U1152);
signed_impls!(I2048, U2048);
conversion_impls!(I2048, U2048, I2112, U2112);
egcd_impls!(I2112, U2048, I2048);
modinv_impls!(I2048);
add_impls!(I2112, I2176, U2176);
signed_impls!(I2112, U2112);
cmp_impls!(I2112);
shift_impls!(I2112, U2112);
subtraction_impls!(I2112, I2176, U2176);
conversion_impls!(I2112, U2112, I2176, U2176);
signed_impls!(I2176, U2176);
signed_impls!(I3072, U3072);
conversion_impls!(I3072, U3072, I3136, U3136);
egcd_impls!(I3136, U3072, I3072);
modinv_impls!(I3072);
add_impls!(I3136, I3200, U3200);
signed_impls!(I3136, U3136);
cmp_impls!(I3136);
shift_impls!(I3136, U3136);
subtraction_impls!(I3136, I3200, U3200);
conversion_impls!(I3136, U3136, I3200, U3200);
signed_impls!(I3200, U3200);
signed_impls!(I4096, U4096);
conversion_impls!(I4096, U4096, I4160, U4160);
egcd_impls!(I4160, U4096, I4096);
modinv_impls!(I4096);
add_impls!(I4160, I4224, U4224);
signed_impls!(I4160, U4160);
cmp_impls!(I4160);
shift_impls!(I4160, U4160);
subtraction_impls!(I4160, I4224, U4224);
conversion_impls!(I4160, U4160, I4224, U4224);
signed_impls!(I4224, U4224);
signed_impls!(I7680, U7680);
conversion_impls!(I7680, U7680, I7744, U7744);
egcd_impls!(I7744, U7680, I7680);
modinv_impls!(I7680);
add_impls!(I7744, I7808, U7808);
signed_impls!(I7744, U7744);
cmp_impls!(I7744);
shift_impls!(I7744, U7744);
subtraction_impls!(I7744, I7808, U7808);
conversion_impls!(I7744, U7744, I7808, U7808);
signed_impls!(I7808, U7808);
signed_impls!(I8192, U8192);
conversion_impls!(I8192, U8192, I8256, U8256);
egcd_impls!(I8256, U8192, I8192);
modinv_impls!(I8192);
add_impls!(I8256, I8320, U8320);
signed_impls!(I8256, U8256);
cmp_impls!(I8256);
shift_impls!(I8256, U8256);
subtraction_impls!(I8256, I8320, U8320);
conversion_impls!(I8256, U8256, I8320, U8320);
signed_impls!(I8320, U8320);
signed_impls!(I15360, U15360);
conversion_impls!(I15360, U15360, I15424, U15424);
egcd_impls!(I15424, U15360, I15360);
modinv_impls!(I15360);
add_impls!(I15424, I15488, U15488);
signed_impls!(I15424, U15424);
cmp_impls!(I15424);
shift_impls!(I15424, U15424);
subtraction_impls!(I15424, I15488, U15488);
conversion_impls!(I15424, U15424, I15488, U15488);
signed_impls!(I15488, U15488);
#[cfg(test)]
mod tests {
mod sigadd {
use super::super::*;
use testing::run_test;
generate_sigadd_tests!(I256, U256, i256, I320, U320);
generate_sigadd_tests!(I320, U320, i320, I384, U384);
generate_sigadd_tests!(I448, U448, i448, I512, U512);
generate_sigadd_tests!(I576, U576, i576, I640, U640);
generate_sigadd_tests!(I640, U640, i640, I704, U704);
generate_sigadd_tests!(I1088, U1088, i1088, I1152, U1152);
generate_sigadd_tests!(I2112, U2112, i2112, I2176, U2176);
generate_sigadd_tests!(I3136, U3136, i3136, I3200, U3200);
generate_sigadd_tests!(I4160, U4160, i4160, I4224, U4224);
generate_sigadd_tests!(I7744, U7744, i7744, I7808, U7808);
generate_sigadd_tests!(I8256, U8256, i8256, I8320, U8320);
generate_sigadd_tests!(I15424, U15424, i15424, I15488, U15488);
}
mod sigsub {
use super::super::*;
use testing::run_test;
generate_sigsub_tests!(I256, U256, i256, I320, U320);
generate_sigsub_tests!(I320, U320, i320, I384, U384);
generate_sigsub_tests!(I448, U448, i448, I512, U512);
generate_sigsub_tests!(I576, U576, i576, I640, U640);
generate_sigsub_tests!(I640, U640, i640, I704, U704);
generate_sigsub_tests!(I1088, U1088, i1088, I1152, U1152);
generate_sigsub_tests!(I2112, U2112, i2112, I2176, U2176);
generate_sigsub_tests!(I3136, U3136, i3136, I3200, U3200);
generate_sigsub_tests!(I4160, U4160, i4160, I4224, U4224);
generate_sigsub_tests!(I7744, U7744, i7744, I7808, U7808);
generate_sigsub_tests!(I8256, U8256, i8256, I8320, U8320);
generate_sigsub_tests!(I15424, U15424, i15424, I15488, U15488);
}
mod signed {
use super::super::*;
use testing::run_test;
generate_signed_tests!(I192, U192, i192);
generate_signed_tests!(I256, U256, i256);
generate_signed_tests!(I320, U320, i320);
generate_signed_tests!(I384, U384, i384);
generate_signed_tests!(I448, U448, i448);
generate_signed_tests!(I512, U512, i512);
generate_signed_tests!(I576, U576, i576);
generate_signed_tests!(I640, U640, i640);
generate_signed_tests!(I704, U704, i704);
generate_signed_tests!(I1024, U1024, i1024);
generate_signed_tests!(I1088, U1088, i1088);
generate_signed_tests!(I1152, U1152, i1152);
generate_signed_tests!(I2048, U2048, i2048);
generate_signed_tests!(I2112, U2112, i2112);
generate_signed_tests!(I2176, U2176, i2176);
generate_signed_tests!(I3072, U3072, i3072);
generate_signed_tests!(I3136, U3136, i3136);
generate_signed_tests!(I3200, U3200, i3200);
generate_signed_tests!(I4096, U4096, i4096);
generate_signed_tests!(I4160, U4160, i4160);
generate_signed_tests!(I4224, U4224, i4224);
generate_signed_tests!(I7680, U7680, i7680);
generate_signed_tests!(I7744, U7744, i7744);
generate_signed_tests!(I7808, U7808, i7808);
generate_signed_tests!(I8192, U8192, i8192);
generate_signed_tests!(I8256, U8256, i8256);
generate_signed_tests!(I8320, U8320, i8320);
generate_signed_tests!(I15360, U15360, i15360);
generate_signed_tests!(I15424, U15424, i15424);
generate_signed_tests!(I15488, U15488, i15488);
}
mod sigconversion {
generate_sigconversion_tests!(I192, U192, i192);
generate_sigconversion_tests!(I256, U256, i256);
generate_sigconversion_tests!(I320, U320, i320);
generate_sigconversion_tests!(I384, U384, i384);
generate_sigconversion_tests!(I448, U448, i448);
generate_sigconversion_tests!(I512, U512, i512);
generate_sigconversion_tests!(I576, U576, i576);
generate_sigconversion_tests!(I640, U640, i640);
generate_sigconversion_tests!(I704, U704, i704);
generate_sigconversion_tests!(I1024, U1024, i1024);
generate_sigconversion_tests!(I1088, U1088, i1088);
generate_sigconversion_tests!(I1152, U1152, i1152);
generate_sigconversion_tests!(I2048, U2048, i2048);
generate_sigconversion_tests!(I2112, U2112, i2112);
generate_sigconversion_tests!(I2176, U2176, i2176);
generate_sigconversion_tests!(I3072, U3072, i3072);
generate_sigconversion_tests!(I3136, U3136, i3136);
generate_sigconversion_tests!(I3200, U3200, i3200);
generate_sigconversion_tests!(I4096, U4096, i4096);
generate_sigconversion_tests!(I4160, U4160, i4160);
generate_sigconversion_tests!(I4224, U4224, i4224);
generate_sigconversion_tests!(I7680, U7680, i7680);
generate_sigconversion_tests!(I7744, U7744, i7744);
generate_sigconversion_tests!(I7808, U7808, i7808);
generate_sigconversion_tests!(I8192, U8192, i8192);
generate_sigconversion_tests!(I8256, U8256, i8256);
generate_sigconversion_tests!(I8320, U8320, i8320);
generate_sigconversion_tests!(I15360, U15360, i15360);
generate_sigconversion_tests!(I15424, U15424, i15424);
generate_sigconversion_tests!(I15488, U15488, i15488);
}
mod sigcmp {
use super::super::*;
use testing::run_test;
generate_sigcmp_tests!(I256, U256, i256);
generate_sigcmp_tests!(I320, U320, i320);
generate_sigcmp_tests!(I448, U448, i448);
generate_sigcmp_tests!(I576, U576, i576);
generate_sigcmp_tests!(I640, U640, i640);
generate_sigcmp_tests!(I1088, U1088, i1088);
generate_sigcmp_tests!(I2112, U2112, i2112);
generate_sigcmp_tests!(I3136, U3136, i3136);
generate_sigcmp_tests!(I4160, U4160, i4160);
generate_sigcmp_tests!(I7744, U7744, i7744);
generate_sigcmp_tests!(I8256, U8256, i8256);
generate_sigcmp_tests!(I15424, U15424, i15424);
}
mod sigshiftl {
use super::super::*;
use testing::run_test;
generate_sigshiftl_tests!(I256, U256, i256);
generate_sigshiftl_tests!(I320, U320, i320);
generate_sigshiftl_tests!(I448, U448, i448);
generate_sigshiftl_tests!(I576, U576, i576);
generate_sigshiftl_tests!(I640, U640, i640);
generate_sigshiftl_tests!(I1088, U1088, i1088);
generate_sigshiftl_tests!(I2112, U2112, i2112);
generate_sigshiftl_tests!(I3136, U3136, i3136);
generate_sigshiftl_tests!(I4160, U4160, i4160);
generate_sigshiftl_tests!(I7744, U7744, i7744);
generate_sigshiftl_tests!(I8256, U8256, i8256);
generate_sigshiftl_tests!(I15424, U15424, i15424);
}
mod sigshiftr {
use super::super::*;
use testing::run_test;
generate_sigshiftr_tests!(I256, U256, i256);
generate_sigshiftr_tests!(I320, U320, i320);
generate_sigshiftr_tests!(I448, U448, i448);
generate_sigshiftr_tests!(I576, U576, i576);
generate_sigshiftr_tests!(I640, U640, i640);
generate_sigshiftr_tests!(I1088, U1088, i1088);
generate_sigshiftr_tests!(I2112, U2112, i2112);
generate_sigshiftr_tests!(I3136, U3136, i3136);
generate_sigshiftr_tests!(I4160, U4160, i4160);
generate_sigshiftr_tests!(I7744, U7744, i7744);
generate_sigshiftr_tests!(I8256, U8256, i8256);
generate_sigshiftr_tests!(I15424, U15424, i15424);
}
mod egcd {
use super::super::*;
use testing::run_test;
generate_egcd_tests!(I192, U192, i192, I256, U256);
generate_egcd_tests!(I256, U256, i256, I320, U320);
generate_egcd_tests!(I384, U384, i384, I448, U448);
generate_egcd_tests!(I512, U512, i512, I576, U576);
generate_egcd_tests!(I576, U576, i576, I640, U640);
generate_egcd_tests!(ignore I1024, U1024, i1024, I1088, U1088);
generate_egcd_tests!(ignore I2048, U2048, i2048, I2112, U2112);
generate_egcd_tests!(ignore I3072, U3072, i3072, I3136, U3136);
generate_egcd_tests!(ignore I4096, U4096, i4096, I4160, U4160);
generate_egcd_tests!(ignore I7680, U7680, i7680, I7744, U7744);
generate_egcd_tests!(ignore I8192, U8192, i8192, I8256, U8256);
generate_egcd_tests!(ignore I15360, U15360, i15360, I15424, U15424);
}
mod modinv {
use super::super::*;
use testing::run_test;
generate_modinv_tests!(I192, U192, i192);
generate_modinv_tests!(I256, U256, i256);
generate_modinv_tests!(I384, U384, i384);
generate_modinv_tests!(I512, U512, i512);
generate_modinv_tests!(I576, U576, i576);
generate_modinv_tests!(I1024, U1024, i1024);
generate_modinv_tests!(I2048, U2048, i2048);
generate_modinv_tests!(I3072, U3072, i3072);
generate_modinv_tests!(I4096, U4096, i4096);
generate_modinv_tests!(I7680, U7680, i7680);
generate_modinv_tests!(I8192, U8192, i8192);
generate_modinv_tests!(ignore I15360, U15360, i15360);
}
}

27
src/signed/mod.rs Normal file
View File

@@ -0,0 +1,27 @@
#[macro_use]
mod add;
#[macro_use]
mod base;
#[macro_use]
mod compare;
#[macro_use]
mod conversion;
#[macro_use]
mod egcd;
#[macro_use]
mod modinv;
#[macro_use]
mod shift;
#[macro_use]
mod subtraction;
use std::cmp::{Ord,Ordering,PartialOrd};
use std::fmt;
use std::ops::{Add,AddAssign};
use std::ops::{Shl,ShlAssign,Shr,ShrAssign};
use std::ops::{Sub,SubAssign};
use unsigned::*;
pub use self::egcd::EGCD;
include!("invoc.rs");

14
src/signed/modinv.rs Normal file
View File

@@ -0,0 +1,14 @@
macro_rules! modinv_impls {
($sname: ident) => {
};
}
#[cfg(test)]
macro_rules! generate_modinv_tests {
($sname: ident, $tname: ident, $mname: ident) => {
};
(ignore $sname: ident, $tname: ident, $mname: ident) => {
};
(body $sname: ident, $tname: ident, $mname: ident) => {
};
}

135
src/signed/shift.rs Normal file
View File

@@ -0,0 +1,135 @@
macro_rules! shift_impls
{
($sname: ident, $name: ident) => {
impl ShlAssign<usize> for $sname {
fn shl_assign(&mut self, amt: usize) {
self.value <<= amt;
if self.value.is_zero() {
self.negative = false;
}
}
}
impl Shl<usize> for $sname {
type Output = $sname;
fn shl(mut self, amt: usize) -> $sname {
self <<= amt;
self
}
}
impl<'a> Shl<usize> for &'a $sname {
type Output = $sname;
fn shl(self, amt: usize) -> $sname {
let mut res = self.clone();
res <<= amt;
res
}
}
impl ShrAssign<usize> for $sname {
fn shr_assign(&mut self, amt: usize) {
// arithmatic right shift is normal right shift, but always rounding
// to negative infinity. To implement this, we first shift right by
// rhs bits, and then shift that value back left rhs bits. If the two
// are the same, we just cleared out even bits, and there's no rounding
// to worry about. If they aren't the same, then we add one back.
let original = self.value.clone();
self.value >>= amt;
if self.negative {
let review = self.value.clone() << amt;
if review != original {
self.value += $name::from(1u64);
}
}
if self.value.is_zero() {
self.negative = false;
}
}
}
impl Shr<usize> for $sname {
type Output = $sname;
fn shr(mut self, amt: usize) -> $sname {
self >>= amt;
self
}
}
impl<'a> Shr<usize> for &'a $sname {
type Output = $sname;
fn shr(self, amt: usize) -> $sname {
let mut res = self.clone();
res >>= amt;
res
}
}
}
}
#[cfg(test)]
macro_rules! generate_sigshiftl_tests {
($sname: ident, $name: ident, $lname: ident) => {
#[test]
fn $lname() {
generate_sigshiftl_tests!(body $sname, $name, $lname);
}
};
(ignore $sname: ident, $name: ident, $lname: ident) => {
#[test]
#[ignore]
fn $lname() {
generate_sigshiftl_tests!(body $sname, $name, $lname);
}
};
(body $sname: ident, $name: ident, $lname: ident) => {
let fname = format!("testdata/sigshiftl/{}.tests", stringify!($sname));
run_test(fname.to_string(), 3, |case| {
let (nega, abytes) = case.get("a").unwrap();
let (neg1, lbytes) = case.get("l").unwrap();
let (negr, rbytes) = case.get("r").unwrap();
assert!(!neg1);
let a = $sname::new(*nega, $name::from_bytes(abytes));
let l = $name::from_bytes(lbytes);
let r = $sname::new(*negr, $name::from_bytes(rbytes));
assert_eq!(r, a << usize::from(l));
});
};
}
#[cfg(test)]
macro_rules! generate_sigshiftr_tests {
($sname: ident, $name: ident, $lname: ident) => {
#[test]
fn $lname() {
generate_sigshiftr_tests!(body $sname, $name, $lname);
}
};
(ignore $sname: ident, $name: ident, $lname: ident) => {
#[test]
#[ignore]
fn $lname() {
generate_sigshiftr_tests!(body $sname, $name, $lname);
}
};
(body $sname: ident, $name: ident, $lname: ident) => {
let fname = format!("testdata/sigshiftr/{}.tests", stringify!($sname));
run_test(fname.to_string(), 3, |case| {
let (nega, abytes) = case.get("a").unwrap();
let (neg1, lbytes) = case.get("l").unwrap();
let (negr, rbytes) = case.get("r").unwrap();
assert!(!neg1);
let a = $sname::new(*nega, $name::from_bytes(abytes));
let l = $name::from_bytes(lbytes);
let r = $sname::new(*negr, $name::from_bytes(rbytes));
assert_eq!(r, a >> usize::from(l));
});
};
}

113
src/signed/subtraction.rs Normal file
View File

@@ -0,0 +1,113 @@
macro_rules! subtraction_impls
{
($name: ident, $bigger: ident, $ubigger: ident) => {
impl SubAssign<$name> for $name {
fn sub_assign(&mut self, rhs: $name) {
self.sub_assign(&rhs);
}
}
impl<'a> SubAssign<&'a $name> for $name {
fn sub_assign(&mut self, rhs: &$name) {
if self.negative == rhs.negative {
if &self.value >= &rhs.value {
self.value -= &rhs.value;
} else {
self.value = rhs.value.clone() - self.value.clone();
self.negative = !self.negative;
}
} else {
unsafe_addition(&mut self.value.value, &rhs.value.value, true);
}
}
}
impl Sub<$name> for $name {
type Output = $bigger;
fn sub(self, rhs: $name) -> $bigger
{
&self - &rhs
}
}
impl<'a> Sub<&'a $name> for $name {
type Output = $bigger;
fn sub(self, rhs: &$name) -> $bigger
{
&self - rhs
}
}
impl<'a> Sub<$name> for &'a $name {
type Output = $bigger;
fn sub(self, rhs: $name) -> $bigger
{
self - &rhs
}
}
impl<'a,'b> Sub<&'a $name> for &'b $name {
type Output = $bigger;
fn sub(self, rhs: &$name) -> $bigger
{
if self.negative == rhs.negative {
if &self.value >= &rhs.value {
$bigger {
negative: self.negative,
value: $ubigger::from(&self.value - &rhs.value)
}
} else {
$bigger {
negative: !self.negative,
value: $ubigger::from(&rhs.value - &self.value)
}
}
} else {
$bigger {
negative: self.negative,
value: &self.value + &rhs.value
}
}
}
}
}
}
#[cfg(test)]
macro_rules! generate_sigsub_tests {
($sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
#[test]
fn $lname() {
generate_sigsub_tests!(body$sname, $name, $lname, $bigger, $ubigger);
}
};
(ignore $sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
#[test]
#[ignore]
fn $lname() {
generate_sigsub_tests!(body $sname, $name, $lname, $bigger, $ubigger);
}
};
(body $sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
let fname = format!("testdata/sigsub/{}.tests", stringify!($sname));
run_test(fname.to_string(), 3, |case| {
let (nega, abytes) = case.get("a").unwrap();
let (negb, bbytes) = case.get("b").unwrap();
let (negc, cbytes) = case.get("c").unwrap();
let mut a = $sname::new(*nega, $name::from_bytes(abytes));
let b = $sname::new(*negb, $name::from_bytes(bbytes));
let c = $bigger::new(*negc, $ubigger::from_bytes(cbytes));
assert_eq!(c, &a - &b, "base subtraction");
if c.value.value[c.value.value.len()-1] == 0 {
a -= b;
assert_eq!($sname::from(c), a, "in-place subtraction");
}
});
};
}

View File

@@ -9,6 +9,7 @@ square_impls!(U192, U384, 192);
conversion_impls!(U192, U256);
conversion_impls!(U192, U384);
conversion_impls!(U192, U448);
addition_impls!(U256, U320);
base_impls!(U256, 4);
barrett_impl!(BarrettU256, U256, U320, U512, U576);
modexp_impls!(U256, U256);
@@ -16,17 +17,24 @@ modexp_impls!(U256, BarrettU256);
modmul_impls!(U256, U512, BarrettU256);
modsq_impls!(U256, U512, BarrettU256);
multiply_impls!(U256, U512);
shift_impls!(U256, 4);
square_impls!(U256, U512, 256);
subtraction_impls!(U256, 4);
conversion_impls!(U256, U320);
conversion_impls!(U256, U384);
conversion_impls!(U256, U448);
conversion_impls!(U256, U512);
conversion_impls!(U256, U576);
addition_impls!(U320, U384);
base_impls!(U320, 5);
multiply_impls!(U320, U640);
shift_impls!(U320, 5);
subtraction_impls!(U320, 5);
conversion_impls!(U320, U384);
conversion_impls!(U320, U512);
conversion_impls!(U320, U576);
conversion_impls!(U320, U640);
addition_impls!(U384, U448);
base_impls!(U384, 6);
barrett_impl!(BarrettU384, U384, U448, U768, U832);
div_impls!(U384, U768);
@@ -50,6 +58,7 @@ conversion_impls!(U448, U512);
conversion_impls!(U448, U768);
conversion_impls!(U448, U832);
conversion_impls!(U448, U896);
addition_impls!(U512, U576);
base_impls!(U512, 8);
barrett_impl!(BarrettU512, U512, U576, U1024, U1088);
div_impls!(U512, U1024);
@@ -80,12 +89,18 @@ conversion_impls!(U576, U1024);
conversion_impls!(U576, U1088);
conversion_impls!(U576, U1152);
conversion_impls!(U576, U1216);
addition_impls!(U640, U704);
base_impls!(U640, 10);
multiply_impls!(U640, U1280);
shift_impls!(U640, 10);
subtraction_impls!(U640, 10);
conversion_impls!(U640, U704);
conversion_impls!(U640, U1152);
conversion_impls!(U640, U1216);
conversion_impls!(U640, U1280);
addition_impls!(U704, U768);
base_impls!(U704, 11);
conversion_impls!(U704, U768);
addition_impls!(U768, U832);
base_impls!(U768, 12);
div_impls!(U768, U1536);
@@ -213,11 +228,19 @@ square_impls!(U3072, U6144, 3072);
conversion_impls!(U3072, U3136);
conversion_impls!(U3072, U6144);
conversion_impls!(U3072, U6208);
addition_impls!(U3136, U3200);
base_impls!(U3136, 49);
multiply_impls!(U3136, U6272);
shift_impls!(U3136, 49);
subtraction_impls!(U3136, 49);
conversion_impls!(U3136, U3200);
conversion_impls!(U3136, U6144);
conversion_impls!(U3136, U6208);
conversion_impls!(U3136, U6272);
addition_impls!(U3200, U3264);
base_impls!(U3200, 50);
conversion_impls!(U3200, U3264);
base_impls!(U3264, 51);
addition_impls!(U4096, U4160);
base_impls!(U4096, 64);
barrett_impl!(BarrettU4096, U4096, U4160, U8192, U8256);
@@ -276,11 +299,19 @@ square_impls!(U7680, U15360, 7680);
conversion_impls!(U7680, U7744);
conversion_impls!(U7680, U15360);
conversion_impls!(U7680, U15424);
addition_impls!(U7744, U7808);
base_impls!(U7744, 121);
multiply_impls!(U7744, U15488);
shift_impls!(U7744, 121);
subtraction_impls!(U7744, 121);
conversion_impls!(U7744, U7808);
conversion_impls!(U7744, U15360);
conversion_impls!(U7744, U15424);
conversion_impls!(U7744, U15488);
addition_impls!(U7808, U7872);
base_impls!(U7808, 122);
conversion_impls!(U7808, U7872);
base_impls!(U7872, 123);
addition_impls!(U8192, U8256);
base_impls!(U8192, 128);
barrett_impl!(BarrettU8192, U8192, U8256, U16384, U16448);
@@ -345,8 +376,11 @@ conversion_impls!(U15424, U15488);
conversion_impls!(U15424, U30720);
conversion_impls!(U15424, U30784);
conversion_impls!(U15424, U30848);
addition_impls!(U15488, U15552);
base_impls!(U15488, 242);
shift_impls!(U15488, 242);
conversion_impls!(U15488, U15552);
base_impls!(U15552, 243);
addition_impls!(U16384, U16448);
base_impls!(U16384, 256);
div_impls!(U16384, U32768);
@@ -427,6 +461,7 @@ mod tests {
generate_base_tests!(U512, u512);
generate_base_tests!(U576, u576);
generate_base_tests!(U640, u640);
generate_base_tests!(U704, u704);
generate_base_tests!(U768, u768);
generate_base_tests!(U832, u832);
generate_base_tests!(U896, u896);
@@ -450,6 +485,8 @@ mod tests {
generate_base_tests!(U2496, u2496);
generate_base_tests!(U3072, u3072);
generate_base_tests!(U3136, u3136);
generate_base_tests!(U3200, u3200);
generate_base_tests!(U3264, u3264);
generate_base_tests!(U4096, u4096);
generate_base_tests!(U4160, u4160);
generate_base_tests!(U4224, u4224);
@@ -459,6 +496,8 @@ mod tests {
generate_base_tests!(U6272, u6272);
generate_base_tests!(U7680, u7680);
generate_base_tests!(U7744, u7744);
generate_base_tests!(U7808, u7808);
generate_base_tests!(U7872, u7872);
generate_base_tests!(U8192, u8192);
generate_base_tests!(U8256, u8256);
generate_base_tests!(U8320, u8320);
@@ -470,6 +509,7 @@ mod tests {
generate_base_tests!(U15360, u15360);
generate_base_tests!(U15424, u15424);
generate_base_tests!(U15488, u15488);
generate_base_tests!(U15552, u15552);
generate_base_tests!(ignore U16384, u16384);
generate_base_tests!(ignore U16448, u16448);
generate_base_tests!(ignore U16512, u16512);
@@ -496,6 +536,7 @@ mod tests {
generate_conversion_tests!(U512, u512);
generate_conversion_tests!(U576, u576);
generate_conversion_tests!(U640, u640);
generate_conversion_tests!(U704, u704);
generate_conversion_tests!(U768, u768);
generate_conversion_tests!(U832, u832);
generate_conversion_tests!(U896, u896);
@@ -519,6 +560,8 @@ mod tests {
generate_conversion_tests!(U2496, u2496);
generate_conversion_tests!(U3072, u3072);
generate_conversion_tests!(U3136, u3136);
generate_conversion_tests!(U3200, u3200);
generate_conversion_tests!(U3264, u3264);
generate_conversion_tests!(U4096, u4096);
generate_conversion_tests!(U4160, u4160);
generate_conversion_tests!(U4224, u4224);
@@ -528,6 +571,8 @@ mod tests {
generate_conversion_tests!(U6272, u6272);
generate_conversion_tests!(U7680, u7680);
generate_conversion_tests!(U7744, u7744);
generate_conversion_tests!(U7808, u7808);
generate_conversion_tests!(U7872, u7872);
generate_conversion_tests!(U8192, u8192);
generate_conversion_tests!(U8256, u8256);
generate_conversion_tests!(U8320, u8320);
@@ -539,6 +584,7 @@ mod tests {
generate_conversion_tests!(U15360, u15360);
generate_conversion_tests!(U15424, u15424);
generate_conversion_tests!(U15488, u15488);
generate_conversion_tests!(U15552, u15552);
generate_conversion_tests!(U16384, u16384);
generate_conversion_tests!(U16448, u16448);
generate_conversion_tests!(U16512, u16512);
@@ -565,6 +611,7 @@ mod tests {
generate_codec_tests!(U512, u512);
generate_codec_tests!(U576, u576);
generate_codec_tests!(U640, u640);
generate_codec_tests!(U704, u704);
generate_codec_tests!(U768, u768);
generate_codec_tests!(U832, u832);
generate_codec_tests!(U896, u896);
@@ -588,6 +635,8 @@ mod tests {
generate_codec_tests!(U2496, u2496);
generate_codec_tests!(U3072, u3072);
generate_codec_tests!(U3136, u3136);
generate_codec_tests!(U3200, u3200);
generate_codec_tests!(U3264, u3264);
generate_codec_tests!(U4096, u4096);
generate_codec_tests!(U4160, u4160);
generate_codec_tests!(U4224, u4224);
@@ -597,6 +646,8 @@ mod tests {
generate_codec_tests!(U6272, u6272);
generate_codec_tests!(U7680, u7680);
generate_codec_tests!(U7744, u7744);
generate_codec_tests!(U7808, u7808);
generate_codec_tests!(U7872, u7872);
generate_codec_tests!(U8192, u8192);
generate_codec_tests!(U8256, u8256);
generate_codec_tests!(U8320, u8320);
@@ -608,6 +659,7 @@ mod tests {
generate_codec_tests!(U15360, u15360);
generate_codec_tests!(U15424, u15424);
generate_codec_tests!(U15488, u15488);
generate_codec_tests!(U15552, u15552);
generate_codec_tests!(U16384, u16384);
generate_codec_tests!(U16448, u16448);
generate_codec_tests!(U16512, u16512);
@@ -637,6 +689,7 @@ mod tests {
generate_cmp_tests!(U512, u512);
generate_cmp_tests!(U576, u576);
generate_cmp_tests!(U640, u640);
generate_cmp_tests!(U704, u704);
generate_cmp_tests!(U768, u768);
generate_cmp_tests!(U832, u832);
generate_cmp_tests!(U896, u896);
@@ -660,6 +713,8 @@ mod tests {
generate_cmp_tests!(U2496, u2496);
generate_cmp_tests!(U3072, u3072);
generate_cmp_tests!(U3136, u3136);
generate_cmp_tests!(U3200, u3200);
generate_cmp_tests!(U3264, u3264);
generate_cmp_tests!(U4096, u4096);
generate_cmp_tests!(U4160, u4160);
generate_cmp_tests!(U4224, u4224);
@@ -669,6 +724,8 @@ mod tests {
generate_cmp_tests!(U6272, u6272);
generate_cmp_tests!(U7680, u7680);
generate_cmp_tests!(U7744, u7744);
generate_cmp_tests!(U7808, u7808);
generate_cmp_tests!(U7872, u7872);
generate_cmp_tests!(U8192, u8192);
generate_cmp_tests!(U8256, u8256);
generate_cmp_tests!(U8320, u8320);
@@ -680,6 +737,7 @@ mod tests {
generate_cmp_tests!(U15360, u15360);
generate_cmp_tests!(U15424, u15424);
generate_cmp_tests!(U15488, u15488);
generate_cmp_tests!(U15552, u15552);
generate_cmp_tests!(ignore U16384, u16384);
generate_cmp_tests!(ignore U16448, u16448);
generate_cmp_tests!(ignore U16512, u16512);
@@ -701,8 +759,11 @@ mod tests {
use super::super::*;
use testing::run_test;
generate_sub_tests!(U256, u256);
generate_sub_tests!(U320, u320);
generate_sub_tests!(U448, u448);
generate_sub_tests!(U576, u576);
generate_sub_tests!(U640, u640);
generate_sub_tests!(U768, u768);
generate_sub_tests!(U832, u832);
generate_sub_tests!(U896, u896);
@@ -717,10 +778,12 @@ mod tests {
generate_sub_tests!(U2176, u2176);
generate_sub_tests!(U2304, u2304);
generate_sub_tests!(U2432, u2432);
generate_sub_tests!(U3136, u3136);
generate_sub_tests!(U4096, u4096);
generate_sub_tests!(U4160, u4160);
generate_sub_tests!(U4224, u4224);
generate_sub_tests!(U6208, u6208);
generate_sub_tests!(U7744, u7744);
generate_sub_tests!(U8192, u8192);
generate_sub_tests!(U8256, u8256);
generate_sub_tests!(U8320, u8320);
@@ -742,6 +805,8 @@ mod tests {
use super::super::*;
use testing::run_test;
generate_shiftl_tests!(U256, u256);
generate_shiftl_tests!(U320, u320);
generate_shiftl_tests!(U384, u384);
generate_shiftl_tests!(U448, u448);
generate_shiftl_tests!(U512, u512);
@@ -758,12 +823,14 @@ mod tests {
generate_shiftl_tests!(U2048, u2048);
generate_shiftl_tests!(U2112, u2112);
generate_shiftl_tests!(U2176, u2176);
generate_shiftl_tests!(U3136, u3136);
generate_shiftl_tests!(U4096, u4096);
generate_shiftl_tests!(U4160, u4160);
generate_shiftl_tests!(U4224, u4224);
generate_shiftl_tests!(U6144, u6144);
generate_shiftl_tests!(U6208, u6208);
generate_shiftl_tests!(U6272, u6272);
generate_shiftl_tests!(U7744, u7744);
generate_shiftl_tests!(U8192, u8192);
generate_shiftl_tests!(U8256, u8256);
generate_shiftl_tests!(U8320, u8320);
@@ -781,6 +848,8 @@ mod tests {
use super::super::*;
use testing::run_test;
generate_shiftr_tests!(U256, u256);
generate_shiftr_tests!(U320, u320);
generate_shiftr_tests!(U384, u384);
generate_shiftr_tests!(U448, u448);
generate_shiftr_tests!(U512, u512);
@@ -797,12 +866,14 @@ mod tests {
generate_shiftr_tests!(U2048, u2048);
generate_shiftr_tests!(U2112, u2112);
generate_shiftr_tests!(U2176, u2176);
generate_shiftr_tests!(U3136, u3136);
generate_shiftr_tests!(U4096, u4096);
generate_shiftr_tests!(U4160, u4160);
generate_shiftr_tests!(U4224, u4224);
generate_shiftr_tests!(U6144, u6144);
generate_shiftr_tests!(U6208, u6208);
generate_shiftr_tests!(U6272, u6272);
generate_shiftr_tests!(U7744, u7744);
generate_shiftr_tests!(U8192, u8192);
generate_shiftr_tests!(U8256, u8256);
generate_shiftr_tests!(U8320, u8320);
@@ -820,8 +891,14 @@ mod tests {
use super::super::*;
use testing::run_test;
generate_add_tests!(U256, u256, U320);
generate_add_tests!(U320, u320, U384);
generate_add_tests!(U384, u384, U448);
generate_add_tests!(U448, u448, U512);
generate_add_tests!(U512, u512, U576);
generate_add_tests!(U576, u576, U640);
generate_add_tests!(U640, u640, U704);
generate_add_tests!(U704, u704, U768);
generate_add_tests!(U768, u768, U832);
generate_add_tests!(U832, u832, U896);
generate_add_tests!(U896, u896, U960);
@@ -836,16 +913,21 @@ mod tests {
generate_add_tests!(U2176, u2176, U2240);
generate_add_tests!(U2304, u2304, U2368);
generate_add_tests!(U2432, u2432, U2496);
generate_add_tests!(U3136, u3136, U3200);
generate_add_tests!(U3200, u3200, U3264);
generate_add_tests!(U4096, u4096, U4160);
generate_add_tests!(U4160, u4160, U4224);
generate_add_tests!(U4224, u4224, U4288);
generate_add_tests!(U6208, u6208, U6272);
generate_add_tests!(U7744, u7744, U7808);
generate_add_tests!(U7808, u7808, U7872);
generate_add_tests!(U8192, u8192, U8256);
generate_add_tests!(U8256, u8256, U8320);
generate_add_tests!(U8320, u8320, U8384);
generate_add_tests!(ignore U12288, u12288, U12352);
generate_add_tests!(ignore U12416, u12416, U12480);
generate_add_tests!(ignore U15424, u15424, U15488);
generate_add_tests!(ignore U15488, u15488, U15552);
generate_add_tests!(ignore U16384, u16384, U16448);
generate_add_tests!(ignore U16448, u16448, U16512);
generate_add_tests!(ignore U16512, u16512, U16576);

View File

@@ -29,18 +29,23 @@ mod square;
#[macro_use]
mod sub;
use self::add::{addition,unsafe_addition};
use self::base::CryptoNum;
pub use self::base::CryptoNum;
pub use self::codec::{Encoder,Decoder};
pub use self::div::DivMod;
pub use self::modexp::ModExp;
pub use self::modmul::ModMul;
pub use self::modsq::ModSquare;
pub use self::square::Square;
pub(crate) use self::add::unsafe_addition;
use self::add::addition;
use self::cmp::compare;
use self::codec::{Encoder,Decoder,raw_decoder};
use self::div::{DivMod,get_number_size};
use self::codec::raw_decoder;
use self::div::get_number_size;
use self::formatter::tochar;
use self::modexp::ModExp;
use self::modmul::ModMul;
use self::modsq::ModSquare;
use self::mul::multiply;
use self::shifts::{shiftl,shiftr};
use self::square::Square;
use self::sub::subtract;
use std::cmp::{Ordering,min};
use std::fmt;

3003
testdata/add/U15488.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/add/U256.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/add/U3136.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/add/U320.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/add/U3200.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/add/U384.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/add/U512.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/add/U640.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/add/U704.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/add/U7744.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/add/U7808.tests vendored Normal file

File diff suppressed because it is too large Load Diff

6006
testdata/base/U15552.tests vendored Normal file

File diff suppressed because it is too large Load Diff

6006
testdata/base/U3200.tests vendored Normal file

File diff suppressed because it is too large Load Diff

6006
testdata/base/U3264.tests vendored Normal file

File diff suppressed because it is too large Load Diff

6006
testdata/base/U704.tests vendored Normal file

File diff suppressed because it is too large Load Diff

6006
testdata/base/U7808.tests vendored Normal file

File diff suppressed because it is too large Load Diff

6006
testdata/base/U7872.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/cmp/U15552.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/cmp/U3200.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/cmp/U3264.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/cmp/U704.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/cmp/U7808.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/cmp/U7872.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/egcd/I1024.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/egcd/I15360.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/egcd/I192.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/egcd/I2048.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/egcd/I256.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/egcd/I3072.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/egcd/I384.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/egcd/I4096.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/egcd/I512.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/egcd/I576.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/egcd/I7680.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/egcd/I8192.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/modinv/I1024.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/modinv/I15360.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/modinv/I192.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/modinv/I2048.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/modinv/I256.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/modinv/I3072.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/modinv/I384.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/modinv/I4096.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/modinv/I512.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/modinv/I576.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/modinv/I7680.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/modinv/I8192.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/shiftl/U256.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/shiftl/U3136.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/shiftl/U320.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/shiftl/U7744.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/shiftr/U256.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/shiftr/U3136.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/shiftr/U320.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/shiftr/U7744.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/sigadd/I1088.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/sigadd/I15424.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/sigadd/I2112.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/sigadd/I256.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/sigadd/I3136.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/sigadd/I320.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/sigadd/I4160.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/sigadd/I448.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/sigadd/I576.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/sigadd/I640.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/sigadd/I7744.tests vendored Normal file

File diff suppressed because it is too large Load Diff

3003
testdata/sigadd/I8256.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/sigcmp/I1088.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/sigcmp/I15424.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/sigcmp/I2112.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/sigcmp/I256.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/sigcmp/I3136.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/sigcmp/I320.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/sigcmp/I4160.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/sigcmp/I448.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/sigcmp/I576.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/sigcmp/I640.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/sigcmp/I7744.tests vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/sigcmp/I8256.tests vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/signed/I1024.tests vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/signed/I1088.tests vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/signed/I1152.tests vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/signed/I15360.tests vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/signed/I15424.tests vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/signed/I15488.tests vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/signed/I192.tests vendored Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More