diff --git a/generation/src/Add.hs b/generation/src/Add.hs index 2542221..2e52b25 100644 --- a/generation/src/Add.hs +++ b/generation/src/Add.hs @@ -38,8 +38,8 @@ unsafeAddOps = File { testCase = Just generateUnsafeTests } -declareSafeAddOperators :: Word -> SourceFile Span -declareSafeAddOperators bitsize = +declareSafeAddOperators :: Word -> [Word] -> SourceFile Span +declareSafeAddOperators bitsize _ = let sname = mkIdent ("U" ++ show bitsize) dname = mkIdent ("U" ++ show (bitsize + 64)) fullRippleAdd = makeRippleAdder True (bitsize `div` 64) "res" @@ -115,8 +115,8 @@ declareSafeAddOperators bitsize = } |] -declareUnsafeAddOperators :: Word -> SourceFile Span -declareUnsafeAddOperators bitsize = +declareUnsafeAddOperators :: Word -> [Word] -> SourceFile Span +declareUnsafeAddOperators bitsize _ = let sname = mkIdent ("U" ++ show bitsize) fullRippleAdd = makeRippleAdder False (bitsize `div` 64) "self" testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty diff --git a/generation/src/Base.hs b/generation/src/Base.hs index 955f54a..99caf7b 100644 --- a/generation/src/Base.hs +++ b/generation/src/Base.hs @@ -20,8 +20,8 @@ base = File { testCase = Nothing } -declareBaseStructure :: Word -> SourceFile Span -declareBaseStructure bitsize = +declareBaseStructure :: Word -> [Word] -> SourceFile Span +declareBaseStructure bitsize _ = let tname = "U" ++ show bitsize entries = bitsize `div` 64 sname = mkIdent tname diff --git a/generation/src/BinaryOps.hs b/generation/src/BinaryOps.hs index ff7b2f2..e999a60 100644 --- a/generation/src/BinaryOps.hs +++ b/generation/src/BinaryOps.hs @@ -28,8 +28,8 @@ binaryOps = File { testCase = Just generateTests } -declareBinaryOperators :: Word -> SourceFile Span -declareBinaryOperators bitsize = +declareBinaryOperators :: Word -> [Word] -> SourceFile Span +declareBinaryOperators bitsize _ = let struct_name = mkIdent ("U" ++ show bitsize) entries = bitsize `div` 64 andOps = generateBinOps "BitAnd" struct_name "bitand" BitAndOp entries diff --git a/generation/src/Compare.hs b/generation/src/Compare.hs index 9ebd39a..017fcd9 100644 --- a/generation/src/Compare.hs +++ b/generation/src/Compare.hs @@ -24,8 +24,8 @@ comparisons = File { testCase = Just generateTests } -declareComparators :: Word -> SourceFile Span -declareComparators bitsize = +declareComparators :: Word -> [Word] -> SourceFile Span +declareComparators bitsize _ = let sname = mkIdent ("U" ++ show bitsize) entries = bitsize `div` 64 eqStatements = buildEqStatements 0 entries diff --git a/generation/src/Conversions.hs b/generation/src/Conversions.hs index 99e890c..b3f8804 100644 --- a/generation/src/Conversions.hs +++ b/generation/src/Conversions.hs @@ -20,8 +20,8 @@ conversions = File { testCase = Nothing } -declareConversions :: Word -> SourceFile Span -declareConversions bitsize = +declareConversions :: Word -> [Word] -> SourceFile Span +declareConversions bitsize otherSizes = let sname = mkIdent ("U" ++ show bitsize) entries = bitsize `div` 64 u8_prims = buildPrimitives sname (mkIdent "u8") entries @@ -36,13 +36,14 @@ declareConversions bitsize = i64_prims = generateSignedPrims sname (mkIdent "u64") (mkIdent "i64") isz_prims = buildPrimitives sname (mkIdent "isize") entries i128_prims = generateI128Primitives sname + others = generateCryptonumConversions bitsize otherSizes in [sourceFile| use core::convert::{From,TryFrom}; use crate::CryptoNum; use crate::ConversionError; #[cfg(test)] use quickcheck::quickcheck; - use super::$$sname; + use super::super::*; $@{u8_prims} $@{u16_prims} @@ -58,6 +59,8 @@ declareConversions bitsize = $@{isz_prims} $@{i128_prims} + $@{others} + #[cfg(test)] quickcheck! { fn u8_recovers(x: u8) -> bool { @@ -244,3 +247,60 @@ generateI128Primitives sname = [ } }|] ] + +generateCryptonumConversions :: Word -> [Word] -> [Item Span] +generateCryptonumConversions source otherSizes = concatMap convert otherSizes + where + sName = mkIdent ("U" ++ show source) + -- + convert target = + let tName = mkIdent ("U" ++ show target) + sEntries = toLit (source `div` 64) + tEntries = toLit (target `div` 64) + in case compare source target of + LT -> [ + [item| + impl<'a> From<&'a $$sName> for $$tName { + fn from(x: &$$sName) -> $$tName { + let mut res = $$tName::zero(); + res.value[0..$$(sEntries)].copy_from_slice(&x.value); + res + } + } + |], + [item| + impl From<$$sName> for $$tName { + fn from(x: $$sName) -> $$tName { + $$tName::from(&x) + } + } + |] + ] + EQ -> [] + GT -> [ + [item| + impl<'a> TryFrom<&'a $$sName> for $$tName { + type Error = ConversionError; + + fn try_from(x: &$$sName) -> Result<$$tName, ConversionError> { + if x.value.iter().skip($$(tEntries)).all(|x| *x == 0) { + let mut res = $$tName::zero(); + res.value.copy_from_slice(&x.value[0..$$(tEntries)]); + Ok(res) + } else { + Err(ConversionError::Overflow) + } + } + } + |], + [item| + impl TryFrom<$$sName> for $$tName { + type Error = ConversionError; + + fn try_from(x: $$sName) -> Result<$$tName, ConversionError> { + $$tName::try_from(&x) + } + } + |] + ] + \ No newline at end of file diff --git a/generation/src/CryptoNum.hs b/generation/src/CryptoNum.hs index c9145b8..3305834 100644 --- a/generation/src/CryptoNum.hs +++ b/generation/src/CryptoNum.hs @@ -28,8 +28,8 @@ cryptoNum = File { testCase = Just generateTests } -declareCryptoNumInstance :: Word -> SourceFile Span -declareCryptoNumInstance bitsize = +declareCryptoNumInstance :: Word -> [Word] -> SourceFile Span +declareCryptoNumInstance bitsize _ = let sname = mkIdent ("U" ++ show bitsize) entries = bitsize `div` 64 entlit = Lit [] (Int Dec (fromIntegral entries) Unsuffixed mempty) mempty diff --git a/generation/src/Division.hs b/generation/src/Division.hs index fc61412..f6bdff3 100644 --- a/generation/src/Division.hs +++ b/generation/src/Division.hs @@ -25,8 +25,8 @@ divisionOps = File { testCase = Just generateDivisionTests } -declareDivision :: Word -> SourceFile Span -declareDivision size = +declareDivision :: Word -> [Word] -> SourceFile Span +declareDivision size _ = let sname = mkIdent ("U" ++ show size) entries = size `div` 64 copyAssign = map doCopy [0..entries-1] diff --git a/generation/src/File.hs b/generation/src/File.hs index fe606c5..c86774e 100644 --- a/generation/src/File.hs +++ b/generation/src/File.hs @@ -26,7 +26,7 @@ data File = File { predicate :: Word -> [Word] -> Bool, outputName :: FilePath, isUnsigned :: Bool, - generator :: Word -> SourceFile Span, + generator :: Word -> [Word] -> SourceFile Span, testCase :: forall g. RandomGen g => Maybe (Word -> g -> [Map String String]) } @@ -62,7 +62,7 @@ generateTasks rng files sizes = basicTasks ++ moduleTasks mainTask = Task { outputFile = "src" signedBit ("u" ++ show size) outputName file ++ ".rs", - writer = \ hndl -> writeSourceFile hndl (generator file size) + writer = \ hndl -> writeSourceFile hndl (generator file size sizes) } in case testCase file of Nothing -> diff --git a/generation/src/Karatsuba.hs b/generation/src/Karatsuba.hs index 59933c2..c7a173a 100644 --- a/generation/src/Karatsuba.hs +++ b/generation/src/Karatsuba.hs @@ -7,6 +7,7 @@ module Karatsuba( Instruction(..) , runChecks + , runQuickCheck , generateInstructions ) where diff --git a/generation/src/ModOps.hs b/generation/src/ModOps.hs index a4e421d..42bc935 100644 --- a/generation/src/ModOps.hs +++ b/generation/src/ModOps.hs @@ -26,8 +26,8 @@ modulusOps = File { testCase = Just generateModulusTests } -declareModOps :: Word -> SourceFile Span -declareModOps bitsize = +declareModOps :: Word -> [Word] -> SourceFile Span +declareModOps bitsize _ = let sname = mkIdent ("U" ++ show bitsize) bname = mkIdent ("U" ++ show (bitsize * 2)) in [sourceFile| diff --git a/generation/src/Multiply.hs b/generation/src/Multiply.hs index 11ee4b3..7295861 100644 --- a/generation/src/Multiply.hs +++ b/generation/src/Multiply.hs @@ -40,8 +40,8 @@ unsafeMultiplyOps = File { testCase = Just generateUnsafeTests } -declareSafeMulOperators :: Word -> SourceFile Span -declareSafeMulOperators bitsize = +declareSafeMulOperators :: Word -> [Word] -> SourceFile Span +declareSafeMulOperators bitsize _ = let sname = mkIdent ("U" ++ show bitsize) dname = mkIdent ("U" ++ show (bitsize * 2)) fullRippleMul = generateMultiplier True (bitsize `div` 64) "rhs" "res" @@ -117,8 +117,8 @@ declareSafeMulOperators bitsize = } |] -declareUnsafeMulOperators :: Word -> SourceFile Span -declareUnsafeMulOperators bitsize = +declareUnsafeMulOperators :: Word -> [Word] -> SourceFile Span +declareUnsafeMulOperators bitsize _ = let sname = mkIdent ("U" ++ show bitsize) halfRippleMul = generateMultiplier False (bitsize `div` 64) "rhs" "self" testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty diff --git a/generation/src/Scale.hs b/generation/src/Scale.hs index c321382..2049e40 100644 --- a/generation/src/Scale.hs +++ b/generation/src/Scale.hs @@ -38,8 +38,8 @@ unsafeScaleOps = File { testCase = Just generateUnsafeTests } -declareSafeScaleOperators :: Word -> SourceFile Span -declareSafeScaleOperators bitsize = +declareSafeScaleOperators :: Word -> [Word] -> SourceFile Span +declareSafeScaleOperators bitsize _ = let sname = mkIdent ("U" ++ show bitsize) dname = mkIdent ("U" ++ show (bitsize + 64)) fullRippleScale = generateScaletiplier True (bitsize `div` 64) "rhs" "res" @@ -154,8 +154,8 @@ declareSafeScaleOperators bitsize = } |] -declareUnsafeScaleOperators :: Word -> SourceFile Span -declareUnsafeScaleOperators bitsize = +declareUnsafeScaleOperators :: Word -> [Word] -> SourceFile Span +declareUnsafeScaleOperators bitsize _ = let sname = mkIdent ("U" ++ show bitsize) halfRippleScale = generateScaletiplier False (bitsize `div` 64) "rhs" "self" testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty diff --git a/generation/src/Shift.hs b/generation/src/Shift.hs index 45492a4..5b85554 100644 --- a/generation/src/Shift.hs +++ b/generation/src/Shift.hs @@ -26,8 +26,8 @@ shiftOps = File { testCase = Just generateTests } -declareShiftOperators :: Word -> SourceFile Span -declareShiftOperators bitsize = +declareShiftOperators :: Word -> [Word] -> SourceFile Span +declareShiftOperators bitsize _ = let struct_name = mkIdent ("U" ++ show bitsize) entries = bitsize `div` 64 unsignedShifts = generateUnsigneds struct_name diff --git a/generation/src/Subtract.hs b/generation/src/Subtract.hs index 7867d40..0498dff 100644 --- a/generation/src/Subtract.hs +++ b/generation/src/Subtract.hs @@ -38,8 +38,8 @@ unsafeSubtractOps = File { testCase = Just generateUnsafeTests } -declareSafeSubtractOperators :: Word -> SourceFile Span -declareSafeSubtractOperators bitsize = +declareSafeSubtractOperators :: Word -> [Word] -> SourceFile Span +declareSafeSubtractOperators bitsize _ = let sname = mkIdent ("U" ++ show bitsize) dname = mkIdent ("U" ++ show (bitsize + 64)) fullRippleSubtract = makeRippleSubtracter True (bitsize `div` 64) "res" @@ -106,8 +106,8 @@ declareSafeSubtractOperators bitsize = } |] -declareUnsafeSubtractOperators :: Word -> SourceFile Span -declareUnsafeSubtractOperators bitsize = +declareUnsafeSubtractOperators :: Word -> [Word] -> SourceFile Span +declareUnsafeSubtractOperators bitsize _ = let sname = mkIdent ("U" ++ show bitsize) fullRippleSubtract = makeRippleSubtracter False (bitsize `div` 64) "self" testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty