Better support for conversions between number types.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|]
|
||||
]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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 ->
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
module Karatsuba(
|
||||
Instruction(..)
|
||||
, runChecks
|
||||
, runQuickCheck
|
||||
, generateInstructions
|
||||
)
|
||||
where
|
||||
|
||||
@@ -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|
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user