Support generating signed numbers.

This commit is contained in:
2020-01-14 12:13:40 -10:00
parent 4383b67c44
commit e46cfe56d1
15 changed files with 218 additions and 30 deletions

View File

@@ -14,6 +14,7 @@ import ModOps(modulusOps)
import Multiply(safeMultiplyOps, unsafeMultiplyOps) import Multiply(safeMultiplyOps, unsafeMultiplyOps)
import Scale(safeScaleOps, unsafeScaleOps) import Scale(safeScaleOps, unsafeScaleOps)
import Shift(shiftOps) import Shift(shiftOps)
import Signed(signedBaseOps)
import Subtract(safeSubtractOps,unsafeSubtractOps) import Subtract(safeSubtractOps,unsafeSubtractOps)
import System.Directory(createDirectoryIfMissing) import System.Directory(createDirectoryIfMissing)
import System.Environment(getArgs) import System.Environment(getArgs)
@@ -53,6 +54,7 @@ unsignedFiles = [
signedFiles :: [File] signedFiles :: [File]
signedFiles = [ signedFiles = [
signedBaseOps
] ]
allFiles :: [File] allFiles :: [File]

View File

@@ -45,6 +45,7 @@ library
Multiply, Multiply,
Scale, Scale,
Shift, Shift,
Signed,
Subtract Subtract
executable generation executable generation

View File

@@ -43,7 +43,7 @@ declareSafeAddOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize) let sname = mkIdent ("U" ++ show bitsize)
dname = mkIdent ("U" ++ show (bitsize + 64)) dname = mkIdent ("U" ++ show (bitsize + 64))
fullRippleAdd = makeRippleAdder True (bitsize `div` 64) "res" fullRippleAdd = makeRippleAdder True (bitsize `div` 64) "res"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile| in [sourceFile|
use core::ops::Add; use core::ops::Add;
use crate::CryptoNum; use crate::CryptoNum;
@@ -119,7 +119,7 @@ declareUnsafeAddOperators :: Word -> [Word] -> SourceFile Span
declareUnsafeAddOperators bitsize _ = declareUnsafeAddOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize) let sname = mkIdent ("U" ++ show bitsize)
fullRippleAdd = makeRippleAdder False (bitsize `div` 64) "self" fullRippleAdd = makeRippleAdder False (bitsize `div` 64) "self"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile| in [sourceFile|
use core::ops::AddAssign; use core::ops::AddAssign;
#[cfg(test)] #[cfg(test)]

View File

@@ -4,7 +4,6 @@ module Base(
) )
where where
-- This is a comment
import File import File
import Language.Rust.Data.Ident import Language.Rust.Data.Ident
import Language.Rust.Data.Position import Language.Rust.Data.Position

View File

@@ -37,7 +37,7 @@ declareBinaryOperators bitsize _ =
xorOps = generateBinOps "BitXor" struct_name "bitxor" BitXorOp entries xorOps = generateBinOps "BitXor" struct_name "bitxor" BitXorOp entries
baseNegationStmts = negationStatements "self" entries baseNegationStmts = negationStatements "self" entries
refNegationStmts = negationStatements "output" entries refNegationStmts = negationStatements "output" entries
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile| in [sourceFile|
use core::ops::{BitAnd,BitAndAssign}; use core::ops::{BitAnd,BitAndAssign};
use core::ops::{BitOr,BitOrAssign}; use core::ops::{BitOr,BitOrAssign};

View File

@@ -30,7 +30,7 @@ declareComparators bitsize _ =
entries = bitsize `div` 64 entries = bitsize `div` 64
eqStatements = buildEqStatements 0 entries eqStatements = buildEqStatements 0 entries
compareExp = buildCompareExp 0 entries compareExp = buildCompareExp 0 entries
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile| in [sourceFile|
use core::cmp::{Eq,Ordering,PartialEq}; use core::cmp::{Eq,Ordering,PartialEq};
#[cfg(test)] #[cfg(test)]

View File

@@ -43,7 +43,7 @@ declareCryptoNumInstance bitsize _ =
Tree (Token mempty (LiteralTok (IntegerTok (show bytelen)) Nothing)) Tree (Token mempty (LiteralTok (IntegerTok (show bytelen)) Nothing))
]) ])
entrieslit = toLit entries entrieslit = toLit entries
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile| in [sourceFile|
use core::cmp::min; use core::cmp::min;
#[cfg(test)] #[cfg(test)]

View File

@@ -30,7 +30,7 @@ declareDivision size _ =
let sname = mkIdent ("U" ++ show size) let sname = mkIdent ("U" ++ show size)
entries = size `div` 64 entries = size `div` 64
copyAssign = map doCopy [0..entries-1] copyAssign = map doCopy [0..entries-1]
testFileLit = Lit [] (Str (testFile size) Cooked Unsuffixed mempty) mempty testFileLit = Lit [] (Str (testFile True size) Cooked Unsuffixed mempty) mempty
in [sourceFile| in [sourceFile|
use core::ops::{Div, DivAssign}; use core::ops::{Div, DivAssign};
use core::ops::{Rem, RemAssign}; use core::ops::{Rem, RemAssign};

View File

@@ -35,8 +35,9 @@ data Task = Task {
writer :: Handle -> IO () writer :: Handle -> IO ()
} }
testFile :: Word -> FilePath testFile :: Bool -> Word -> FilePath
testFile size = "U" ++ show5 size ++ ".test" testFile True size = "U" ++ show5 size ++ ".test"
testFile False size = "I" ++ show5 size ++ ".test"
show5 :: Word -> String show5 :: Word -> String
show5 = go . show show5 = go . show
@@ -58,9 +59,10 @@ generateTasks rng files sizes = basicTasks ++ moduleTasks
| otherwise = | otherwise =
let (myg, theirg) = split g let (myg, theirg) = split g
tasks = go theirg files' rest tasks = go theirg files' rest
signedBit = if isUnsigned file then "unsigned" else "signed" (signedBit, prefix) | isUnsigned file = ("unsigned", "u")
| otherwise = ("signed", "i")
mainTask = Task { mainTask = Task {
outputFile = "src" </> signedBit </> ("u" ++ show size) </> outputFile = "src" </> signedBit </> (prefix ++ show size) </>
outputName file ++ ".rs", outputName file ++ ".rs",
writer = \ hndl -> writeSourceFile hndl (generator file size sizes) writer = \ hndl -> writeSourceFile hndl (generator file size sizes)
} }
@@ -69,16 +71,16 @@ generateTasks rng files sizes = basicTasks ++ moduleTasks
mainTask : tasks mainTask : tasks
Just caseGenerator -> Just caseGenerator ->
let testTask = Task { let testTask = Task {
outputFile = "testdata" </> outputName file </> testFile size, outputFile = "testdata" </> outputName file </> testFile (isUnsigned file) size,
writer = \ hndl -> writeTestCase hndl (caseGenerator size myg) writer = \ hndl -> writeTestCase hndl (caseGenerator size myg)
} }
in testTask : mainTask : tasks in testTask : mainTask : tasks
generateModules :: [Task] -> [Task] generateModules :: [Task] -> [Task]
generateModules tasks = Map.foldrWithKey maddModule [] fileMap ++ [unsignedTask] generateModules tasks = Map.foldrWithKey maddModule [] fileMap ++ [signedTask, unsignedTask]
where where
maddModule path mods acc maddModule path mods acc
| "src/unsigned" `isPrefixOf` path = | ("src/unsigned" `isPrefixOf` path) || ("src/signed" `isPrefixOf` path) =
let (basePath, lowerName) = splitFileName (init path) let (basePath, lowerName) = splitFileName (init path)
upperName = map toUpper lowerName upperName = map toUpper lowerName
task = Task { task = Task {
@@ -97,26 +99,28 @@ generateModules tasks = Map.foldrWithKey maddModule [] fileMap ++ [unsignedTask]
file = dropExtension fileext file = dropExtension fileext
in Map.insertWith (++) dir [file] acc in Map.insertWith (++) dir [file] acc
-- --
unsignedTask = signedTask = moduleTask "signed"
let mods = Map.foldrWithKey topModule [] fileMap unsignedTask = moduleTask "unsigned"
pubuses = Map.foldrWithKey pubUse [] fileMap moduleTask kind =
let mods = Map.foldrWithKey (topModule kind) [] fileMap
pubuses = Map.foldrWithKey (pubUse kind) [] fileMap
in Task { in Task {
outputFile = "src" </> "unsigned.rs", outputFile = "src" </> (kind ++ ".rs"),
writer = \ hndl -> writer = \ hndl ->
writeSourceFile hndl [sourceFile| writeSourceFile hndl [sourceFile|
$@{mods} $@{mods}
$@{pubuses} $@{pubuses}
|] |]
} }
topModule path _ acc topModule kind path _ acc
| "src/unsigned" `isPrefixOf` path = | ("src/" ++ kind) `isPrefixOf` path =
let lowerName = takeFileName (init path) let lowerName = takeFileName (init path)
modl = mkIdent lowerName modl = mkIdent lowerName
in [item| mod $$modl; |] : acc in [item| mod $$modl; |] : acc
| otherwise = | otherwise =
acc acc
pubUse path _ acc pubUse kind path _ acc
| "src/unsigned" `isPrefixOf` path = | ("src/" ++ kind) `isPrefixOf` path =
let lowerName = takeFileName (init path) let lowerName = takeFileName (init path)
tname = mkIdent (map toUpper lowerName) tname = mkIdent (map toUpper lowerName)
modl = mkIdent lowerName modl = mkIdent lowerName

View File

@@ -29,7 +29,7 @@ declareModOps :: Word -> [Word] -> SourceFile Span
declareModOps bitsize _ = declareModOps bitsize _ =
let sname = mkIdent ("U" ++ show bitsize) let sname = mkIdent ("U" ++ show bitsize)
bname = mkIdent ("U" ++ show (bitsize * 2)) bname = mkIdent ("U" ++ show (bitsize * 2))
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile| in [sourceFile|
use core::convert::TryFrom; use core::convert::TryFrom;
use crate::unsigned::{$$sname, $$bname}; use crate::unsigned::{$$sname, $$bname};

View File

@@ -45,7 +45,7 @@ declareSafeMulOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize) let sname = mkIdent ("U" ++ show bitsize)
dname = mkIdent ("U" ++ show (bitsize * 2)) dname = mkIdent ("U" ++ show (bitsize * 2))
fullRippleMul = generateMultiplier True (bitsize `div` 64) "rhs" "res" fullRippleMul = generateMultiplier True (bitsize `div` 64) "rhs" "res"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile| in [sourceFile|
use core::ops::Mul; use core::ops::Mul;
use crate::CryptoNum; use crate::CryptoNum;
@@ -121,7 +121,7 @@ declareUnsafeMulOperators :: Word -> [Word] -> SourceFile Span
declareUnsafeMulOperators bitsize _ = declareUnsafeMulOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize) let sname = mkIdent ("U" ++ show bitsize)
halfRippleMul = generateMultiplier False (bitsize `div` 64) "rhs" "self" halfRippleMul = generateMultiplier False (bitsize `div` 64) "rhs" "self"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile| in [sourceFile|
use core::ops::MulAssign; use core::ops::MulAssign;
#[cfg(test)] #[cfg(test)]

View File

@@ -43,7 +43,7 @@ declareSafeScaleOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize) let sname = mkIdent ("U" ++ show bitsize)
dname = mkIdent ("U" ++ show (bitsize + 64)) dname = mkIdent ("U" ++ show (bitsize + 64))
fullRippleScale = generateScaletiplier True (bitsize `div` 64) "rhs" "res" fullRippleScale = generateScaletiplier True (bitsize `div` 64) "rhs" "res"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile| in [sourceFile|
use core::ops::Mul; use core::ops::Mul;
use crate::CryptoNum; use crate::CryptoNum;
@@ -158,7 +158,7 @@ declareUnsafeScaleOperators :: Word -> [Word] -> SourceFile Span
declareUnsafeScaleOperators bitsize _ = declareUnsafeScaleOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize) let sname = mkIdent ("U" ++ show bitsize)
halfRippleScale = generateScaletiplier False (bitsize `div` 64) "rhs" "self" halfRippleScale = generateScaletiplier False (bitsize `div` 64) "rhs" "self"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile| in [sourceFile|
use core::ops::MulAssign; use core::ops::MulAssign;
#[cfg(test)] #[cfg(test)]

View File

@@ -35,7 +35,7 @@ declareShiftOperators bitsize _ =
shlActualImpl = concatMap actualShlImplLines [1..entries-1] shlActualImpl = concatMap actualShlImplLines [1..entries-1]
shrActualImpl = concatMap (actualShrImplLines entries) (reverse [0..entries-1]) shrActualImpl = concatMap (actualShrImplLines entries) (reverse [0..entries-1])
resAssign = map reassignSelf [0..entries-1] resAssign = map reassignSelf [0..entries-1]
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile| in [sourceFile|
#[cfg(test)] #[cfg(test)]
use core::convert::TryFrom; use core::convert::TryFrom;

182
generation/src/Signed.hs Normal file
View File

@@ -0,0 +1,182 @@
{-# LANGUAGE QuasiQuotes #-}
module Signed(signedBaseOps)
where
import File
import Language.Rust.Data.Ident
import Language.Rust.Data.Position
import Language.Rust.Quote
import Language.Rust.Syntax
signedBaseOps :: File
signedBaseOps = File {
predicate = const (const True),
outputName = "base",
isUnsigned = False,
generator = declareSigned,
testCase = Nothing
}
declareSigned :: Word -> [Word] -> SourceFile Span
declareSigned bitsize _ =
let sname = mkIdent ("I" ++ show bitsize)
uname = mkIdent ("U" ++ show bitsize)
in [sourceFile|
use core::fmt;
use core::ops::{Neg, Not};
use crate::CryptoNum;
use crate::unsigned::$$uname;
use quickcheck::{Arbitrary,Gen};
#[cfg(test)]
use quickcheck::quickcheck;
#[derive(Clone)]
pub struct $$sname {
contents: $$uname,
}
impl Neg for $$sname {
type Output = $$sname;
fn neg(mut self) -> $$sname {
for x in self.contents.value.iter_mut() {
*x = !*x;
}
let one = $$uname::from(1u64);
self.contents += one;
self
}
}
impl<'a> Neg for &'a $$sname {
type Output = $$sname;
fn neg(self) -> $$sname {
let res = self.clone();
res.neg()
}
}
impl Not for $$sname {
type Output = $$sname;
fn not(mut self) -> $$sname {
for x in self.contents.value.iter_mut() {
*x = !*x;
}
self
}
}
impl<'a> Not for &'a $$sname {
type Output = $$sname;
fn not(self) -> $$sname {
self.clone().not()
}
}
impl fmt::Debug for $$sname {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.contents)
}
}
impl fmt::UpperHex for $$sname {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut temp = self.clone();
if temp.contents.value[temp.contents.value.len()-1] >> 63 == 1 {
write!(f, "-")?;
temp = !temp;
}
write!(f, "{:X}", temp.contents)
}
}
impl fmt::LowerHex for $$sname {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut temp = self.clone();
if temp.contents.value[temp.contents.value.len()-1] >> 63 == 1 {
write!(f, "-")?;
temp = !temp;
}
write!(f, "{:x}", temp.contents)
}
}
impl PartialEq for $$sname {
fn eq(&self, other: &$$sname) -> bool {
let mut all_equal = true;
for (l, r) in self.contents.value.iter().zip(other.contents.value.iter()) {
all_equal &= *l == *r;
}
all_equal
}
}
impl Eq for $$sname { }
impl Arbitrary for $$sname {
fn arbitrary<G: Gen>(g: &mut G) -> $$sname {
$$sname{
contents: $$uname::arbitrary(g),
}
}
}
impl CryptoNum for $$sname {
fn zero() -> $$sname {
$$sname{ contents: $$uname::zero() }
}
fn is_zero(&self) -> bool {
self.contents.is_zero()
}
fn is_even(&self) -> bool {
self.contents.is_even()
}
fn is_odd(&self) -> bool {
self.contents.is_odd()
}
fn bit_length() -> usize {
$$uname::bit_length()
}
fn mask(&mut self, len: usize) {
self.contents.mask(len);
}
fn testbit(&self, bit: usize) -> bool {
self.contents.testbit(bit)
}
fn from_bytes(bytes: &[u8]) -> $$sname {
$$sname{ contents: $$uname::from_bytes(bytes) }
}
fn to_bytes(&self, bytes: &mut [u8]) {
self.contents.to_bytes(bytes);
}
}
#[cfg(test)]
quickcheck! {
fn equality_reflexive(x: $$sname) -> bool {
&x == &x
}
fn equality_symmetric(x: $$sname, y: $$sname) -> bool {
(&x == &y) == (&y == &x)
}
fn double_not(x: $$sname) -> bool {
x == !!&x
}
fn double_neg(x: $$sname) -> bool {
x == --&x
}
}
|]

View File

@@ -43,7 +43,7 @@ declareSafeSubtractOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize) let sname = mkIdent ("U" ++ show bitsize)
dname = mkIdent ("U" ++ show (bitsize + 64)) dname = mkIdent ("U" ++ show (bitsize + 64))
fullRippleSubtract = makeRippleSubtracter True (bitsize `div` 64) "res" fullRippleSubtract = makeRippleSubtracter True (bitsize `div` 64) "res"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile| in [sourceFile|
use core::ops::Sub; use core::ops::Sub;
use crate::CryptoNum; use crate::CryptoNum;
@@ -110,7 +110,7 @@ declareUnsafeSubtractOperators :: Word -> [Word] -> SourceFile Span
declareUnsafeSubtractOperators bitsize _ = declareUnsafeSubtractOperators bitsize _ =
let sname = mkIdent ("U" ++ show bitsize) let sname = mkIdent ("U" ++ show bitsize)
fullRippleSubtract = makeRippleSubtracter False (bitsize `div` 64) "self" fullRippleSubtract = makeRippleSubtracter False (bitsize `div` 64) "self"
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
in [sourceFile| in [sourceFile|
use core::ops::SubAssign; use core::ops::SubAssign;
#[cfg(test)] #[cfg(test)]