Better support for conversions between number types.
This commit is contained in:
@@ -38,8 +38,8 @@ unsafeAddOps = File {
|
|||||||
testCase = Just generateUnsafeTests
|
testCase = Just generateUnsafeTests
|
||||||
}
|
}
|
||||||
|
|
||||||
declareSafeAddOperators :: Word -> SourceFile Span
|
declareSafeAddOperators :: Word -> [Word] -> SourceFile Span
|
||||||
declareSafeAddOperators bitsize =
|
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"
|
||||||
@@ -115,8 +115,8 @@ declareSafeAddOperators bitsize =
|
|||||||
}
|
}
|
||||||
|]
|
|]
|
||||||
|
|
||||||
declareUnsafeAddOperators :: Word -> SourceFile Span
|
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 bitsize) Cooked Unsuffixed mempty) mempty
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ base = File {
|
|||||||
testCase = Nothing
|
testCase = Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
declareBaseStructure :: Word -> SourceFile Span
|
declareBaseStructure :: Word -> [Word] -> SourceFile Span
|
||||||
declareBaseStructure bitsize =
|
declareBaseStructure bitsize _ =
|
||||||
let tname = "U" ++ show bitsize
|
let tname = "U" ++ show bitsize
|
||||||
entries = bitsize `div` 64
|
entries = bitsize `div` 64
|
||||||
sname = mkIdent tname
|
sname = mkIdent tname
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ binaryOps = File {
|
|||||||
testCase = Just generateTests
|
testCase = Just generateTests
|
||||||
}
|
}
|
||||||
|
|
||||||
declareBinaryOperators :: Word -> SourceFile Span
|
declareBinaryOperators :: Word -> [Word] -> SourceFile Span
|
||||||
declareBinaryOperators bitsize =
|
declareBinaryOperators bitsize _ =
|
||||||
let struct_name = mkIdent ("U" ++ show bitsize)
|
let struct_name = mkIdent ("U" ++ show bitsize)
|
||||||
entries = bitsize `div` 64
|
entries = bitsize `div` 64
|
||||||
andOps = generateBinOps "BitAnd" struct_name "bitand" BitAndOp entries
|
andOps = generateBinOps "BitAnd" struct_name "bitand" BitAndOp entries
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ comparisons = File {
|
|||||||
testCase = Just generateTests
|
testCase = Just generateTests
|
||||||
}
|
}
|
||||||
|
|
||||||
declareComparators :: Word -> SourceFile Span
|
declareComparators :: Word -> [Word] -> SourceFile Span
|
||||||
declareComparators bitsize =
|
declareComparators bitsize _ =
|
||||||
let sname = mkIdent ("U" ++ show bitsize)
|
let sname = mkIdent ("U" ++ show bitsize)
|
||||||
entries = bitsize `div` 64
|
entries = bitsize `div` 64
|
||||||
eqStatements = buildEqStatements 0 entries
|
eqStatements = buildEqStatements 0 entries
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ conversions = File {
|
|||||||
testCase = Nothing
|
testCase = Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
declareConversions :: Word -> SourceFile Span
|
declareConversions :: Word -> [Word] -> SourceFile Span
|
||||||
declareConversions bitsize =
|
declareConversions bitsize otherSizes =
|
||||||
let sname = mkIdent ("U" ++ show bitsize)
|
let sname = mkIdent ("U" ++ show bitsize)
|
||||||
entries = bitsize `div` 64
|
entries = bitsize `div` 64
|
||||||
u8_prims = buildPrimitives sname (mkIdent "u8") entries
|
u8_prims = buildPrimitives sname (mkIdent "u8") entries
|
||||||
@@ -36,13 +36,14 @@ declareConversions bitsize =
|
|||||||
i64_prims = generateSignedPrims sname (mkIdent "u64") (mkIdent "i64")
|
i64_prims = generateSignedPrims sname (mkIdent "u64") (mkIdent "i64")
|
||||||
isz_prims = buildPrimitives sname (mkIdent "isize") entries
|
isz_prims = buildPrimitives sname (mkIdent "isize") entries
|
||||||
i128_prims = generateI128Primitives sname
|
i128_prims = generateI128Primitives sname
|
||||||
|
others = generateCryptonumConversions bitsize otherSizes
|
||||||
in [sourceFile|
|
in [sourceFile|
|
||||||
use core::convert::{From,TryFrom};
|
use core::convert::{From,TryFrom};
|
||||||
use crate::CryptoNum;
|
use crate::CryptoNum;
|
||||||
use crate::ConversionError;
|
use crate::ConversionError;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use quickcheck::quickcheck;
|
use quickcheck::quickcheck;
|
||||||
use super::$$sname;
|
use super::super::*;
|
||||||
|
|
||||||
$@{u8_prims}
|
$@{u8_prims}
|
||||||
$@{u16_prims}
|
$@{u16_prims}
|
||||||
@@ -58,6 +59,8 @@ declareConversions bitsize =
|
|||||||
$@{isz_prims}
|
$@{isz_prims}
|
||||||
$@{i128_prims}
|
$@{i128_prims}
|
||||||
|
|
||||||
|
$@{others}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
quickcheck! {
|
quickcheck! {
|
||||||
fn u8_recovers(x: u8) -> bool {
|
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
|
testCase = Just generateTests
|
||||||
}
|
}
|
||||||
|
|
||||||
declareCryptoNumInstance :: Word -> SourceFile Span
|
declareCryptoNumInstance :: Word -> [Word] -> SourceFile Span
|
||||||
declareCryptoNumInstance bitsize =
|
declareCryptoNumInstance bitsize _ =
|
||||||
let sname = mkIdent ("U" ++ show bitsize)
|
let sname = mkIdent ("U" ++ show bitsize)
|
||||||
entries = bitsize `div` 64
|
entries = bitsize `div` 64
|
||||||
entlit = Lit [] (Int Dec (fromIntegral entries) Unsuffixed mempty) mempty
|
entlit = Lit [] (Int Dec (fromIntegral entries) Unsuffixed mempty) mempty
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ divisionOps = File {
|
|||||||
testCase = Just generateDivisionTests
|
testCase = Just generateDivisionTests
|
||||||
}
|
}
|
||||||
|
|
||||||
declareDivision :: Word -> SourceFile Span
|
declareDivision :: Word -> [Word] -> SourceFile Span
|
||||||
declareDivision size =
|
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]
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ data File = File {
|
|||||||
predicate :: Word -> [Word] -> Bool,
|
predicate :: Word -> [Word] -> Bool,
|
||||||
outputName :: FilePath,
|
outputName :: FilePath,
|
||||||
isUnsigned :: Bool,
|
isUnsigned :: Bool,
|
||||||
generator :: Word -> SourceFile Span,
|
generator :: Word -> [Word] -> SourceFile Span,
|
||||||
testCase :: forall g. RandomGen g => Maybe (Word -> g -> [Map String String])
|
testCase :: forall g. RandomGen g => Maybe (Word -> g -> [Map String String])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ generateTasks rng files sizes = basicTasks ++ moduleTasks
|
|||||||
mainTask = Task {
|
mainTask = Task {
|
||||||
outputFile = "src" </> signedBit </> ("u" ++ show size) </>
|
outputFile = "src" </> signedBit </> ("u" ++ show size) </>
|
||||||
outputName file ++ ".rs",
|
outputName file ++ ".rs",
|
||||||
writer = \ hndl -> writeSourceFile hndl (generator file size)
|
writer = \ hndl -> writeSourceFile hndl (generator file size sizes)
|
||||||
}
|
}
|
||||||
in case testCase file of
|
in case testCase file of
|
||||||
Nothing ->
|
Nothing ->
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
module Karatsuba(
|
module Karatsuba(
|
||||||
Instruction(..)
|
Instruction(..)
|
||||||
, runChecks
|
, runChecks
|
||||||
|
, runQuickCheck
|
||||||
, generateInstructions
|
, generateInstructions
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ modulusOps = File {
|
|||||||
testCase = Just generateModulusTests
|
testCase = Just generateModulusTests
|
||||||
}
|
}
|
||||||
|
|
||||||
declareModOps :: Word -> SourceFile Span
|
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))
|
||||||
in [sourceFile|
|
in [sourceFile|
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ unsafeMultiplyOps = File {
|
|||||||
testCase = Just generateUnsafeTests
|
testCase = Just generateUnsafeTests
|
||||||
}
|
}
|
||||||
|
|
||||||
declareSafeMulOperators :: Word -> SourceFile Span
|
declareSafeMulOperators :: Word -> [Word] -> SourceFile Span
|
||||||
declareSafeMulOperators bitsize =
|
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"
|
||||||
@@ -117,8 +117,8 @@ declareSafeMulOperators bitsize =
|
|||||||
}
|
}
|
||||||
|]
|
|]
|
||||||
|
|
||||||
declareUnsafeMulOperators :: Word -> SourceFile Span
|
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 bitsize) Cooked Unsuffixed mempty) mempty
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ unsafeScaleOps = File {
|
|||||||
testCase = Just generateUnsafeTests
|
testCase = Just generateUnsafeTests
|
||||||
}
|
}
|
||||||
|
|
||||||
declareSafeScaleOperators :: Word -> SourceFile Span
|
declareSafeScaleOperators :: Word -> [Word] -> SourceFile Span
|
||||||
declareSafeScaleOperators bitsize =
|
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"
|
||||||
@@ -154,8 +154,8 @@ declareSafeScaleOperators bitsize =
|
|||||||
}
|
}
|
||||||
|]
|
|]
|
||||||
|
|
||||||
declareUnsafeScaleOperators :: Word -> SourceFile Span
|
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 bitsize) Cooked Unsuffixed mempty) mempty
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ shiftOps = File {
|
|||||||
testCase = Just generateTests
|
testCase = Just generateTests
|
||||||
}
|
}
|
||||||
|
|
||||||
declareShiftOperators :: Word -> SourceFile Span
|
declareShiftOperators :: Word -> [Word] -> SourceFile Span
|
||||||
declareShiftOperators bitsize =
|
declareShiftOperators bitsize _ =
|
||||||
let struct_name = mkIdent ("U" ++ show bitsize)
|
let struct_name = mkIdent ("U" ++ show bitsize)
|
||||||
entries = bitsize `div` 64
|
entries = bitsize `div` 64
|
||||||
unsignedShifts = generateUnsigneds struct_name
|
unsignedShifts = generateUnsigneds struct_name
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ unsafeSubtractOps = File {
|
|||||||
testCase = Just generateUnsafeTests
|
testCase = Just generateUnsafeTests
|
||||||
}
|
}
|
||||||
|
|
||||||
declareSafeSubtractOperators :: Word -> SourceFile Span
|
declareSafeSubtractOperators :: Word -> [Word] -> SourceFile Span
|
||||||
declareSafeSubtractOperators bitsize =
|
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"
|
||||||
@@ -106,8 +106,8 @@ declareSafeSubtractOperators bitsize =
|
|||||||
}
|
}
|
||||||
|]
|
|]
|
||||||
|
|
||||||
declareUnsafeSubtractOperators :: Word -> SourceFile Span
|
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 bitsize) Cooked Unsuffixed mempty) mempty
|
||||||
|
|||||||
Reference in New Issue
Block a user