Better support for conversions between number types.

This commit is contained in:
2020-01-10 09:04:47 -10:00
parent 8c5f18cb7c
commit 4b8d0b3f09
14 changed files with 96 additions and 35 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)
}
}
|]
]

View File

@@ -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

View File

@@ -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]

View File

@@ -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 ->

View File

@@ -7,6 +7,7 @@
module Karatsuba(
Instruction(..)
, runChecks
, runQuickCheck
, generateInstructions
)
where

View File

@@ -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|

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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