Base implementation of signed numbers and EGCD, with tests.
This commit is contained in:
289
generate.hs
289
generate.hs
@@ -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
|
||||
@@ -69,6 +81,26 @@ needs = [ Need ModExp (\ size -> [Req size ModMul
|
||||
, 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'''
|
||||
|
||||
@@ -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
113
src/signed/add.rs
Normal 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
154
src/signed/base.rs
Normal 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
61
src/signed/compare.rs
Normal 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
99
src/signed/conversion.rs
Normal 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
125
src/signed/egcd.rs
Normal 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←u−v, A←A−C,B←B−D;
|
||||
// otherwise,v←v−u, C←C−A, D←D−B.
|
||||
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
315
src/signed/invoc.rs
Normal 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
27
src/signed/mod.rs
Normal 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
14
src/signed/modinv.rs
Normal 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
135
src/signed/shift.rs
Normal 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
113
src/signed/subtraction.rs
Normal 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");
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Reference in New Issue
Block a user