diff --git a/generation/src/BinaryOps.hs b/generation/src/BinaryOps.hs index 73c92c6..7732b6d 100644 --- a/generation/src/BinaryOps.hs +++ b/generation/src/BinaryOps.hs @@ -22,6 +22,10 @@ declareBinaryOperators bitsize = out "use core::ops::{BitOr,BitOrAssign};" out "use core::ops::{BitXor,BitXorAssign};" out "use core::ops::Not;" + out "#[cfg(test)]" + out "use crate::CryptoNum;" + out "#[cfg(test)]" + out "use quickcheck::quickcheck;" out ("use super::U" ++ show bitsize ++ ";") blank generateBinOps "BitAnd" name "bitand" "&=" entries @@ -46,6 +50,8 @@ declareBinaryOperators bitsize = forM_ [0..entries-1] $ \ i -> out ("output.value[" ++ show i ++ "] = !self.value[" ++ show i ++ "];") out "output" + blank + addBinaryLaws name generateBinOps :: String -> String -> String -> String -> Word -> Gen () generateBinOps trait name fun op entries = @@ -90,4 +96,50 @@ generateBinOpsFromAssigns trait name fun op = wrapIndent ("fn " ++ fun ++ "(self, rhs: &" ++ name ++ ") -> " ++ name) $ do out "let mut output = self.clone();" out ("output " ++ op ++ " rhs;") - out "output" \ No newline at end of file + out "output" + +addBinaryLaws :: String -> Gen () +addBinaryLaws name = + do let args3 = "(a: " ++ name ++ ", b: " ++ name ++ ", c: " ++ name ++ ")" + args2 = "(a: " ++ name ++ ", b: " ++ name ++ ")" + out "#[cfg(test)]" + wrapIndent "quickcheck!" $ + do wrapIndent ("fn and_associative" ++ args3 ++ " -> bool") $ + out ("((&a & &b) & &c) == (&a & (&b & &c))") + blank + wrapIndent ("fn and_commutative" ++ args2 ++ " -> bool") $ + out ("(&a & &b) == (&b & &a)") + blank + wrapIndent ("fn and_idempotent" ++ args2 ++ " -> bool") $ + out ("(&a & &b) == (&a & &b & &a)") + blank + wrapIndent ("fn xor_associative" ++ args3 ++ " -> bool") $ + out ("((&a ^ &b) ^ &c) == (&a ^ (&b ^ &c))") + blank + wrapIndent ("fn xor_commutative" ++ args2 ++ " -> bool") $ + out ("(&a ^ &b) == (&b ^ &a)") + blank + wrapIndent ("fn or_associative" ++ args3 ++ " -> bool") $ + out ("((&a | &b) | &c) == (&a | (&b | &c))") + blank + wrapIndent ("fn or_commutative" ++ args2 ++ " -> bool") $ + out ("(&a | &b) == (&b | &a)") + blank + wrapIndent ("fn or_idempotent" ++ args2 ++ " -> bool") $ + out ("(&a | &b) == (&a | &b | &a)") + blank + wrapIndent ("fn and_or_distribution" ++ args3 ++ "-> bool") $ + out ("(&a & (&b | &c)) == ((&a & &b) | (&a & &c))") + blank + wrapIndent ("fn xor_clears(a: " ++ name ++ ") -> bool") $ + out (name ++ "::zero() == (&a ^ &a)") + blank + wrapIndent ("fn double_neg_ident(a: " ++ name ++ ") -> bool") $ + out ("a == !!&a") + blank + wrapIndent ("fn and_ident(a: " ++ name ++ ") -> bool") $ + do out ("let ones = !" ++ name ++ "::zero();") + out ("(&a & &ones) == a") + blank + wrapIndent ("fn or_ident(a: " ++ name ++ ") -> bool") $ + out ("(&a | " ++ name ++ "::zero()) == a") \ No newline at end of file