Start experimenting with full generation of all of the numeric types.
Previously, we used a little bit of generation to drive a lot of Rust macros. This works, but it's a little confusing to read and write. In addition, we used a lot of implementations with variable timings based on their input, which isn't great for crypto. This is the start of an attempt to just generate all of the relevant Rust code directly, and to use timing-channel resistant implementations for most of the routines.
This commit is contained in:
116
old/signed/add.rs
Normal file
116
old/signed/add.rs
Normal file
@@ -0,0 +1,116 @@
|
||||
macro_rules! add_impls
|
||||
{
|
||||
($name: ident, $bigger: ident, $ubigger: ident) => {
|
||||
impl AddAssign<$name> for $name {
|
||||
fn add_assign(&mut self, rhs: $name) {
|
||||
self.add_assign(&rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AddAssign<&'a $name> for $name {
|
||||
fn add_assign(&mut self, rhs: &$name) {
|
||||
if self.negative == rhs.negative {
|
||||
unsafe_addition(&mut self.value.value, &rhs.value.value, true);
|
||||
} else {
|
||||
if self.value > rhs.value {
|
||||
self.value -= rhs.value.clone();
|
||||
} else {
|
||||
self.value = rhs.value.clone() - self.value.clone();
|
||||
self.negative = rhs.negative;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<$name> for $name {
|
||||
type Output = $bigger;
|
||||
|
||||
fn add(self, rhs: $name) -> $bigger
|
||||
{
|
||||
&self + &rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Add<&'a $name> for $name {
|
||||
type Output = $bigger;
|
||||
|
||||
fn add(self, rhs: &$name) -> $bigger
|
||||
{
|
||||
&self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Add<$name> for &'a $name {
|
||||
type Output = $bigger;
|
||||
|
||||
fn add(self, rhs: $name) -> $bigger
|
||||
{
|
||||
self + &rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> Add<&'a $name> for &'b $name {
|
||||
type Output = $bigger;
|
||||
|
||||
fn add(self, rhs: &$name) -> $bigger
|
||||
{
|
||||
if self.negative == rhs.negative {
|
||||
$bigger{
|
||||
negative: self.negative,
|
||||
value: &self.value + &rhs.value
|
||||
}
|
||||
} else {
|
||||
match self.value.cmp(&rhs.value) {
|
||||
Ordering::Greater =>
|
||||
$bigger {
|
||||
negative: self.negative,
|
||||
value: $ubigger::from(&self.value - &rhs.value)
|
||||
},
|
||||
Ordering::Less =>
|
||||
$bigger {
|
||||
negative: rhs.negative,
|
||||
value: $ubigger::from(&rhs.value - &self.value)
|
||||
},
|
||||
Ordering::Equal =>
|
||||
$bigger::zero()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_sigadd_tests {
|
||||
($sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_sigadd_tests!(body$sname, $name, $lname, $bigger, $ubigger);
|
||||
}
|
||||
};
|
||||
(ignore $sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_sigadd_tests!(body $sname, $name, $lname, $bigger, $ubigger);
|
||||
}
|
||||
};
|
||||
(body $sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
|
||||
let fname = build_test_path("sigadd", stringify!($name));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (nega, abytes) = case.get("a").unwrap();
|
||||
let (negb, bbytes) = case.get("b").unwrap();
|
||||
let (negc, cbytes) = case.get("c").unwrap();
|
||||
|
||||
let mut a = $sname::new(*nega, $name::from_bytes(abytes));
|
||||
let b = $sname::new(*negb, $name::from_bytes(bbytes));
|
||||
let c = $bigger::new(*negc, $ubigger::from_bytes(cbytes));
|
||||
assert_eq!(c, &a + &b, "base addition");
|
||||
|
||||
if c.value.value[c.value.value.len()-1] == 0 {
|
||||
a += b;
|
||||
assert_eq!($sname::from(c), a, "mutating addition");
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
182
old/signed/base.rs
Normal file
182
old/signed/base.rs
Normal file
@@ -0,0 +1,182 @@
|
||||
macro_rules! signed_impls {
|
||||
($sname: ident, $name: ident) => {
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct $sname {
|
||||
negative: bool,
|
||||
value: $name
|
||||
}
|
||||
|
||||
impl $sname {
|
||||
/// Generate a new signed number from an unsigned number and a
|
||||
/// boolean describing whether or not the new number is negative.
|
||||
/// Note that if the value is zero, the value of the negative flag
|
||||
/// will be ignored.
|
||||
pub fn new(negative: bool, value: $name) -> $sname {
|
||||
if value.is_zero() {
|
||||
$sname{ negative: false, value: value }
|
||||
} else {
|
||||
$sname{ negative: negative, value: value }
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a new number that is the negated version of this number.
|
||||
pub fn negate(&self) -> $sname {
|
||||
if self.value.is_zero() {
|
||||
self.clone()
|
||||
} else {
|
||||
$sname{ negative: !self.negative, value: self.value.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the absolute value of the number.
|
||||
pub fn abs(&self) -> $sname {
|
||||
$sname{ negative: false, value: self.value.clone() }
|
||||
}
|
||||
|
||||
/// Return true iff the value is negative and not zero.
|
||||
pub fn is_negative(&self) -> bool {
|
||||
self.negative
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$sname> for $name {
|
||||
fn from(x: $sname) -> $name {
|
||||
x.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a $sname> for $name {
|
||||
fn from(x: &$sname) -> $name {
|
||||
x.value.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$name> for $sname {
|
||||
fn from(x: $name) -> $sname {
|
||||
$sname{ negative: false, value: x }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a $name> for $sname {
|
||||
fn from(x: &$name) -> $sname {
|
||||
$sname{ negative: false, value: x.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
impl CryptoNum for $sname {
|
||||
fn zero() -> $sname {
|
||||
$sname{ negative: false, value: $name::zero() }
|
||||
}
|
||||
|
||||
fn bit_length() -> usize {
|
||||
$name::bit_length()
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool {
|
||||
self.value.is_zero()
|
||||
}
|
||||
|
||||
fn is_even(&self) -> bool {
|
||||
self.value.is_even()
|
||||
}
|
||||
|
||||
fn is_odd(&self) -> bool {
|
||||
self.value.is_odd()
|
||||
}
|
||||
|
||||
fn mask(&mut self, len: usize) {
|
||||
self.value.mask(len);
|
||||
}
|
||||
|
||||
fn testbit(&self, bit: usize) -> bool {
|
||||
self.value.testbit(bit)
|
||||
}
|
||||
}
|
||||
|
||||
impl Arbitrary for $sname {
|
||||
fn arbitrary<G>(g: &mut G) -> $sname
|
||||
where G: Gen
|
||||
{
|
||||
let neg = bool::arbitrary(g);
|
||||
let val = $name::arbitrary(g);
|
||||
let neg2 = if val.is_zero() { false } else { neg };
|
||||
$sname{ negative: neg2, value: val }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for $sname {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.negative {
|
||||
f.write_str("-")?;
|
||||
}
|
||||
self.value.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::UpperHex for $sname {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.negative {
|
||||
write!(f, "-{:X}", self.value)
|
||||
} else {
|
||||
if f.sign_plus() {
|
||||
write!(f, "+{:X}", self.value)
|
||||
} else {
|
||||
write!(f, "{:X}", self.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::LowerHex for $sname {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.negative {
|
||||
write!(f, "-{:x}", self.value)
|
||||
} else {
|
||||
if f.sign_plus() {
|
||||
write!(f, "+{:x}", self.value)
|
||||
} else {
|
||||
write!(f, "{:x}", self.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generate_base_conversions!($sname, $name);
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_signed_tests
|
||||
{
|
||||
($sname: ident, $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_signed_tests!(body $sname, $name, $lname);
|
||||
}
|
||||
};
|
||||
(ignore $sname: ident, $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_signed_tests!(body $sname, $name, $lname);
|
||||
}
|
||||
};
|
||||
(body $sname: ident, $name: ident, $lname: ident) => {
|
||||
let fname = build_test_path("signed", stringify!($sname));
|
||||
run_test(fname.to_string(), 4, |case| {
|
||||
let (negx, xbytes) = case.get("x").unwrap();
|
||||
let (neg0, zbytes) = case.get("z").unwrap();
|
||||
let (neg1, ebytes) = case.get("e").unwrap();
|
||||
let (neg2, obytes) = case.get("o").unwrap();
|
||||
|
||||
assert!(!neg0 && !neg1 && !neg2);
|
||||
let x = $sname::new(*negx, $name::from_bytes(xbytes));
|
||||
let z = 1 == zbytes[0];
|
||||
let e = 1 == ebytes[0];
|
||||
let o = 1 == obytes[0];
|
||||
assert_eq!(x.is_zero(), z);
|
||||
assert_eq!(x.is_even(), e);
|
||||
assert_eq!(x.is_odd(), o);
|
||||
});
|
||||
}
|
||||
}
|
||||
61
old/signed/compare.rs
Normal file
61
old/signed/compare.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
macro_rules! cmp_impls {
|
||||
($name: ident) => {
|
||||
impl PartialOrd for $name {
|
||||
fn partial_cmp(&self, rhs: &$name) -> Option<Ordering> {
|
||||
Some(self.cmp(&rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for $name {
|
||||
fn cmp(&self, rhs: &$name) -> Ordering {
|
||||
match (self.negative, rhs.negative) {
|
||||
(false, false) => self.value.cmp(&rhs.value),
|
||||
(true, false) => Ordering::Less,
|
||||
(false, true) => Ordering::Greater,
|
||||
(true, true) => self.value.cmp(&rhs.value).reverse()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_sigcmp_tests {
|
||||
($sname: ident, $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_sigcmp_tests!(body $sname, $name, $lname);
|
||||
}
|
||||
};
|
||||
(ignore $sname: ident, $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_sigcmp_tests!(body $sname, $name, $lname);
|
||||
}
|
||||
};
|
||||
(body $sname: ident, $name: ident, $lname: ident) => {
|
||||
let fname = build_test_path("sigcmp", stringify!($sname));
|
||||
run_test(fname.to_string(), 5, |case| {
|
||||
let (nega, abytes) = case.get("a").unwrap();
|
||||
let (negb, bbytes) = case.get("b").unwrap();
|
||||
let (neg2, ebytes) = case.get("e").unwrap();
|
||||
let (neg3, gbytes) = case.get("g").unwrap();
|
||||
let (neg4, lbytes) = case.get("l").unwrap();
|
||||
|
||||
assert!(!neg2 && !neg3 && !neg4);
|
||||
let a = $sname::new(*nega, $name::from_bytes(abytes));
|
||||
let b = $sname::new(*negb, $name::from_bytes(bbytes));
|
||||
let e = 1 == ebytes[0];
|
||||
let g = 1 == gbytes[0];
|
||||
let l = 1 == lbytes[0];
|
||||
|
||||
assert_eq!(e, a == b, "equals wrong");
|
||||
assert_eq!(g, a > b, "greater than wrong");
|
||||
assert_eq!(l, a < b, "less than wrong");
|
||||
|
||||
assert_eq!(e || g, a >= b, "greater / equals wrong");
|
||||
assert_eq!(e || l, a <= b, "less than / equals wrong");
|
||||
});
|
||||
};
|
||||
}
|
||||
114
old/signed/conversion.rs
Normal file
114
old/signed/conversion.rs
Normal file
@@ -0,0 +1,114 @@
|
||||
macro_rules! generate_base_conversions
|
||||
{
|
||||
($sname: ident, $name: ident) => {
|
||||
generate_base_type_convert!($sname, $name, i8, u8);
|
||||
generate_base_type_convert!($sname, $name, i16, u16);
|
||||
generate_base_type_convert!($sname, $name, i32, u32);
|
||||
generate_base_type_convert!($sname, $name, i64, u64);
|
||||
generate_base_type_convert!($sname, $name, isize, usize);
|
||||
|
||||
impl From<i128> for $sname {
|
||||
fn from(x: i128) -> $sname {
|
||||
$sname{ negative: x < 0, value: $name::from(x.abs() as u128) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for $sname {
|
||||
fn from(x: u64) -> $sname {
|
||||
$sname{ negative: false, value: $name::from(x) }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! generate_base_type_convert
|
||||
{
|
||||
($sname: ident, $name: ident, $sbase: ident, $base: ident) => {
|
||||
impl From<$sbase> for $sname {
|
||||
fn from(x: $sbase) -> $sname {
|
||||
$sname {
|
||||
negative: x < 0,
|
||||
value: $name::from(x.abs() as $base)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$sname> for $sbase {
|
||||
fn from(x: $sname) -> $sbase {
|
||||
let signum = if x.negative { -1 } else { 1 };
|
||||
signum * ($base::from(x.value) as $sbase)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a $sname> for $sbase {
|
||||
fn from(x: &$sname) -> $sbase {
|
||||
let signum = if x.negative { -1 } else { 1 };
|
||||
signum * ($base::from(&x.value) as $sbase)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_sigconversion_tests
|
||||
{
|
||||
($sname: ident, $name: ident, $lname: ident) => {
|
||||
#[cfg(test)]
|
||||
mod $lname {
|
||||
use super::super::super::*;
|
||||
use std::convert::From;
|
||||
|
||||
quickcheck! {
|
||||
fn conversion_i8( x: i8) -> bool { x == i8::from($sname::from(x)) }
|
||||
fn conversion_i16( x: i16) -> bool { x == i16::from($sname::from(x)) }
|
||||
fn conversion_i32( x: i32) -> bool { x == i32::from($sname::from(x)) }
|
||||
fn conversion_i64( x: i64) -> bool { x == i64::from($sname::from(x)) }
|
||||
fn conversion_isize(x: isize) -> bool { x == isize::from($sname::from(x)) }
|
||||
|
||||
fn back_conversion(x: u64, b: bool) -> bool
|
||||
{
|
||||
let mut base = $sname::zero();
|
||||
let xprime = x & 0x7FFFFFFFFFFFFFFF;
|
||||
base.negative = b && (x != 0);
|
||||
base.value.value[0] = xprime;
|
||||
base == $sname::from(i64::from(&base))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! conversion_impls
|
||||
{
|
||||
($sname: ident, $name: ident, $sother: ident, $other: ident) => {
|
||||
impl<'a> From<&'a $sother> for $sname {
|
||||
fn from(x: &$sother) -> $sname {
|
||||
$sname {
|
||||
negative: x.negative,
|
||||
value: $name::from(&x.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a $sname> for $sother {
|
||||
fn from(x: &$sname) -> $sother {
|
||||
$sother {
|
||||
negative: x.negative,
|
||||
value: $other::from(&x.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$sother> for $sname {
|
||||
fn from(x: $sother) -> $sname {
|
||||
$sname::from(&x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$sname> for $sother {
|
||||
fn from(x: $sname) -> $sother {
|
||||
$sother::from(&x)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
156
old/signed/div.rs
Normal file
156
old/signed/div.rs
Normal file
@@ -0,0 +1,156 @@
|
||||
macro_rules! div_impls
|
||||
{
|
||||
($name: ident, $uname: ident) => {
|
||||
impl DivAssign<$name> for $name {
|
||||
fn div_assign(&mut self, rhs: $name) {
|
||||
self.div_assign(&rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DivAssign<&'a $name> for $name {
|
||||
fn div_assign(&mut self, rhs: &$name) {
|
||||
let (q,r) = self.value.divmod(&rhs.value);
|
||||
if self.negative ^ rhs.negative {
|
||||
self.value.value.copy_from_slice(&q.value);
|
||||
if !r.is_zero() {
|
||||
self.value += $uname::from(1u64);
|
||||
}
|
||||
self.negative = !self.value.is_zero();
|
||||
} else {
|
||||
self.value.value.copy_from_slice(&q.value);
|
||||
self.negative = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<$name> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn div(self, rhs: $name) -> $name
|
||||
{
|
||||
&self / &rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Div<&'a $name> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn div(self, rhs: &$name) -> $name
|
||||
{
|
||||
&self / rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Div<$name> for &'a $name {
|
||||
type Output = $name;
|
||||
|
||||
fn div(self, rhs: $name) -> $name
|
||||
{
|
||||
self / &rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> Div<&'a $name> for &'b $name {
|
||||
type Output = $name;
|
||||
|
||||
fn div(self, rhs: &$name) -> $name
|
||||
{
|
||||
let mut outval = self.clone();
|
||||
outval /= rhs;
|
||||
outval
|
||||
}
|
||||
}
|
||||
|
||||
impl RemAssign<$name> for $name {
|
||||
fn rem_assign(&mut self, rhs: $name) {
|
||||
self.rem_assign(&rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> RemAssign<&'a $name> for $name {
|
||||
fn rem_assign(&mut self, rhs: &$name) {
|
||||
if rhs.negative != self.negative {
|
||||
self.negative = !self.negative;
|
||||
let modres = &self.value % &rhs.value;
|
||||
self.value.value.copy_from_slice(&rhs.value.value);
|
||||
self.value -= modres;
|
||||
} else {
|
||||
self.value %= &rhs.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Rem<$name> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn rem(self, rhs: $name) -> $name
|
||||
{
|
||||
&self % &rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Rem<&'a $name> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn rem(self, rhs: &$name) -> $name
|
||||
{
|
||||
&self % rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Rem<$name> for &'a $name {
|
||||
type Output = $name;
|
||||
|
||||
fn rem(self, rhs: $name) -> $name
|
||||
{
|
||||
self % &rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> Rem<&'a $name> for &'b $name {
|
||||
type Output = $name;
|
||||
|
||||
fn rem(self, rhs: &$name) -> $name
|
||||
{
|
||||
let mut outval = self.clone();
|
||||
outval %= rhs;
|
||||
outval
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_sigdiv_tests {
|
||||
($sname: ident, $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_sigdiv_tests!(body $sname, $name);
|
||||
}
|
||||
};
|
||||
(ignore $sname: ident, $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_sigdiv_tests!(body $sname, $name);
|
||||
}
|
||||
};
|
||||
(body $sname: ident, $name: ident) => {
|
||||
let fname = build_test_path("sigdiv", stringify!($sname));
|
||||
run_test(fname.to_string(), 4, |case| {
|
||||
let (nega, abytes) = case.get("a").unwrap();
|
||||
let (negb, bbytes) = case.get("b").unwrap();
|
||||
let (negq, qbytes) = case.get("q").unwrap();
|
||||
let (negr, rbytes) = case.get("r").unwrap();
|
||||
|
||||
let a = $sname::new(*nega, $name::from_bytes(abytes));
|
||||
let b = $sname::new(*negb, $name::from_bytes(bbytes));
|
||||
let q = $sname::new(*negq, $name::from_bytes(qbytes));
|
||||
let r = $sname::new(*negr, $name::from_bytes(rbytes));
|
||||
let d = &a / &b;
|
||||
let m = &a % &b;
|
||||
assert_eq!(q, d, "base div");
|
||||
assert_eq!(r, m, "base mod");
|
||||
});
|
||||
};
|
||||
}
|
||||
226
old/signed/egcd.rs
Normal file
226
old/signed/egcd.rs
Normal file
@@ -0,0 +1,226 @@
|
||||
/// GCD computations, with extended information
|
||||
pub trait EGCD<T: PartialEq + From<u64> + Sized>: Sized {
|
||||
/// Compute the extended GCD for this value and the given value.
|
||||
/// If the inputs to this function are x (self) and y (the argument),
|
||||
/// and the results are (a, b, g), then (a * x) + (b * y) = g.
|
||||
fn egcd(&self, rhs: &Self) -> (T, T, T);
|
||||
/// Compute whether or not the given number and the provided number
|
||||
/// have a GCD of 1. This is a slightly faster version of calling
|
||||
/// `egcd` and testing the result, because it can ignore some
|
||||
/// intermediate values.
|
||||
fn gcd_is_one(&self, rhs: &Self) -> bool {
|
||||
let (_, _, g) = self.egcd(rhs);
|
||||
g == T::from(1u64)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! egcd_impls {
|
||||
($sname: ident, $name: ident, $ssmall: ident, $bigger: ident) => {
|
||||
impl EGCD<$sname> for $ssmall {
|
||||
fn egcd(&self, rhs: &$ssmall) -> ($sname, $sname, $sname) {
|
||||
// This slower version works when we can't guarantee that the
|
||||
// inputs are positive.
|
||||
let mut s = $sname::from(0i64);
|
||||
let mut old_s = $sname::from(1i64);
|
||||
let mut t = $sname::from(1i64);
|
||||
let mut old_t = $sname::from(0i64);
|
||||
let mut r = $sname::from(rhs);
|
||||
let mut old_r = $sname::from(self);
|
||||
|
||||
while !r.is_zero() {
|
||||
let quotient = &old_r / &r;
|
||||
|
||||
let prov_r = r.clone();
|
||||
let prov_s = s.clone();
|
||||
let prov_t = t.clone();
|
||||
|
||||
// FIXME: Make this less copying, although I suspect the
|
||||
// division above is the more major problem.
|
||||
r = $sname::from($bigger::from(old_r) - (r * "ient));
|
||||
s = $sname::from($bigger::from(old_s) - (s * "ient));
|
||||
t = $sname::from($bigger::from(old_t) - (t * "ient));
|
||||
|
||||
old_r = prov_r;
|
||||
old_s = prov_s;
|
||||
old_t = prov_t;
|
||||
}
|
||||
|
||||
if old_r.is_negative() {
|
||||
(old_s.negate(), old_t.negate(), old_r.negate())
|
||||
} else {
|
||||
(old_s, old_t, old_r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EGCD<$sname> for $name {
|
||||
fn egcd(&self, rhs: &$name) -> ($sname, $sname, $sname) {
|
||||
// INPUT: two positive integers x and y.
|
||||
let mut x = $sname::from($ssmall::from(self));
|
||||
let mut y = $sname::from($ssmall::from(rhs));
|
||||
// OUTPUT: integers a, b, and v such that ax + by = v,
|
||||
// where v = gcd(x, y).
|
||||
// 1. g←1.
|
||||
let mut gshift = 0;
|
||||
// 2. While x and y are both even, do the following: x←x/2,
|
||||
// y←y/2, g←2g.
|
||||
while x.is_even() && y.is_even() {
|
||||
x >>= 1;
|
||||
y >>= 1;
|
||||
gshift += 1;
|
||||
}
|
||||
// 3. u←x, v←y, A←1, B←0, C←0, D←1.
|
||||
let mut u = x.clone();
|
||||
let mut v = y.clone();
|
||||
#[allow(non_snake_case)]
|
||||
let mut A = $sname::from(1i64);
|
||||
#[allow(non_snake_case)]
|
||||
let mut B = $sname::zero();
|
||||
#[allow(non_snake_case)]
|
||||
let mut C = $sname::zero();
|
||||
#[allow(non_snake_case)]
|
||||
let mut D = $sname::from(1i64);
|
||||
loop {
|
||||
// 4. While u is even do the following:
|
||||
while u.is_even() {
|
||||
// 4.1 u←u/2.
|
||||
u >>= 1;
|
||||
// 4.2 If A≡B≡0 (mod 2) then A←A/2, B←B/2; otherwise,
|
||||
// A←(A + y)/2, B←(B − x)/2.
|
||||
if A.is_even() && B.is_even() {
|
||||
A >>= 1;
|
||||
B >>= 1;
|
||||
} else {
|
||||
A += &y;
|
||||
A >>= 1;
|
||||
B -= &x;
|
||||
B >>= 1;
|
||||
}
|
||||
}
|
||||
// 5. While v is even do the following:
|
||||
while v.is_even() {
|
||||
// 5.1 v←v/2.
|
||||
v >>= 1;
|
||||
// 5.2 If C ≡ D ≡ 0 (mod 2) then C←C/2, D←D/2; otherwise,
|
||||
// C←(C + y)/2, D←(D − x)/2.
|
||||
if C.is_even() && D.is_even() {
|
||||
C >>= 1;
|
||||
D >>= 1;
|
||||
} else {
|
||||
C += &y;
|
||||
C >>= 1;
|
||||
D -= &x;
|
||||
D >>= 1;
|
||||
}
|
||||
}
|
||||
// 6. If u≥v then u←u−v, A←A−C,B←B−D;
|
||||
// otherwise,v←v−u, C←C−A, D←D−B.
|
||||
if u >= v {
|
||||
u -= &v;
|
||||
A -= &C;
|
||||
B -= &D;
|
||||
} else {
|
||||
v -= &u;
|
||||
C -= &A;
|
||||
D -= &B;
|
||||
}
|
||||
// 7. If u = 0, then a←C, b←D, and return(a, b, g · v);
|
||||
// otherwise, go to step 4.
|
||||
if u.is_zero() {
|
||||
return (C, D, v << gshift);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn gcd_is_one(&self, b: &$name) -> bool {
|
||||
let mut u = self.clone();
|
||||
let mut v = b.clone();
|
||||
let one = $name::from(1u64);
|
||||
|
||||
if u.is_zero() {
|
||||
return v == one;
|
||||
}
|
||||
|
||||
if v.is_zero() {
|
||||
return u == one;
|
||||
}
|
||||
|
||||
if u.is_even() && v.is_even() {
|
||||
return false;
|
||||
}
|
||||
|
||||
while u.is_even() {
|
||||
u >>= 1;
|
||||
}
|
||||
|
||||
loop {
|
||||
while v.is_even() {
|
||||
v >>= 1;
|
||||
}
|
||||
// u and v guaranteed to be odd right now.
|
||||
if u > v {
|
||||
// make sure that v > u, so that our subtraction works
|
||||
// out.
|
||||
let t = u;
|
||||
u = v;
|
||||
v = t;
|
||||
}
|
||||
v = v - &u;
|
||||
|
||||
if v.is_zero() {
|
||||
return u == one;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_egcd_tests {
|
||||
($sname: ident, $uname: ident, $tname: ident, $sname64: ident, $uname64: ident) => {
|
||||
#[test]
|
||||
fn $tname() {
|
||||
generate_egcd_tests!(body $sname, $uname, $tname, $sname64, $uname64);
|
||||
}
|
||||
};
|
||||
(ignore $sname: ident, $uname: ident, $tname: ident, $sname64: ident, $uname64: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $tname() {
|
||||
generate_egcd_tests!(body $sname, $uname, $tname, $sname64, $uname64);
|
||||
}
|
||||
};
|
||||
(body $sname: ident, $uname: ident, $tname: ident, $sname64: ident, $uname64: ident) => {
|
||||
let fname = build_test_path("egcd", stringify!($sname));
|
||||
run_test(fname.to_string(), 5, |case| {
|
||||
let (negx, xbytes) = case.get("x").unwrap();
|
||||
let (negy, ybytes) = case.get("y").unwrap();
|
||||
let (negv, vbytes) = case.get("v").unwrap();
|
||||
let (nega, abytes) = case.get("a").unwrap();
|
||||
let (negb, bbytes) = case.get("b").unwrap();
|
||||
|
||||
let v = $sname64::new(*negv, $uname64::from_bytes(vbytes));
|
||||
let a = $sname64::new(*nega, $uname64::from_bytes(abytes));
|
||||
let b = $sname64::new(*negb, $uname64::from_bytes(bbytes));
|
||||
|
||||
if *negx || *negy {
|
||||
let x = $sname::new(*negx, $uname::from_bytes(xbytes));
|
||||
let y = $sname::new(*negy, $uname::from_bytes(ybytes));
|
||||
let (mya, myb, myv) = x.egcd(&y);
|
||||
assert_eq!(v, myv, "Signed GCD test");
|
||||
assert_eq!(a, mya, "Signed X factor test");
|
||||
assert_eq!(b, myb, "Signed Y factor tst");
|
||||
assert_eq!(x.gcd_is_one(&y), (myv == $sname64::from(1i64)));
|
||||
} else {
|
||||
let x = $uname::from_bytes(xbytes);
|
||||
let y = $uname::from_bytes(ybytes);
|
||||
let (mya, myb, myv) = x.egcd(&y);
|
||||
assert_eq!(v, myv, "GCD test");
|
||||
assert_eq!(a, mya, "X factor test");
|
||||
assert_eq!(b, myb, "Y factor tst");
|
||||
assert_eq!(x.gcd_is_one(&y), (myv == $sname64::from(1i64)));
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
740
old/signed/invoc.rs
Normal file
740
old/signed/invoc.rs
Normal file
@@ -0,0 +1,740 @@
|
||||
moddiv_impls!(I192, I384);
|
||||
signed_impls!(I192, U192);
|
||||
subtraction_impls!(I192, I256, U256);
|
||||
mul_impls!(I192, I384);
|
||||
div_impls!(I192, U192);
|
||||
smodinv_impls!(I192, I256);
|
||||
scale_impls!(I192, I256);
|
||||
conversion_impls!(I192, U192, I256, U256);
|
||||
conversion_impls!(I192, U192, I384, U384);
|
||||
conversion_impls!(I192, U192, I448, U448);
|
||||
egcd_impls!(I256, U192, I192, I512);
|
||||
modinv_impls!(U192, I256, U256);
|
||||
moddiv_impls!(I256, I512);
|
||||
add_impls!(I256, I320, U320);
|
||||
signed_impls!(I256, U256);
|
||||
cmp_impls!(I256);
|
||||
shift_impls!(I256, U256);
|
||||
subtraction_impls!(I256, I320, U320);
|
||||
mul_impls!(I256, I512);
|
||||
div_impls!(I256, U256);
|
||||
smodinv_impls!(I256, I320);
|
||||
scale_impls!(I256, I320);
|
||||
conversion_impls!(I256, U256, I320, U320);
|
||||
conversion_impls!(I256, U256, I512, U512);
|
||||
conversion_impls!(I256, U256, I576, U576);
|
||||
egcd_impls!(I320, U256, I256, I640);
|
||||
modinv_impls!(U256, I320, U320);
|
||||
add_impls!(I320, I384, U384);
|
||||
signed_impls!(I320, U320);
|
||||
cmp_impls!(I320);
|
||||
shift_impls!(I320, U320);
|
||||
subtraction_impls!(I320, I384, U384);
|
||||
mul_impls!(I320, I640);
|
||||
div_impls!(I320, U320);
|
||||
scale_impls!(I320, I384);
|
||||
conversion_impls!(I320, U320, I384, U384);
|
||||
conversion_impls!(I320, U320, I640, U640);
|
||||
conversion_impls!(I320, U320, I704, U704);
|
||||
moddiv_impls!(I384, I768);
|
||||
signed_impls!(I384, U384);
|
||||
shift_impls!(I384, U384);
|
||||
subtraction_impls!(I384, I448, U448);
|
||||
mul_impls!(I384, I768);
|
||||
div_impls!(I384, U384);
|
||||
smodinv_impls!(I384, I448);
|
||||
scale_impls!(I384, I448);
|
||||
conversion_impls!(I384, U384, I448, U448);
|
||||
conversion_impls!(I384, U384, I768, U768);
|
||||
conversion_impls!(I384, U384, I832, U832);
|
||||
egcd_impls!(I448, U384, I384, I896);
|
||||
modinv_impls!(U384, I448, U448);
|
||||
moddiv_impls!(I448, I896);
|
||||
add_impls!(I448, I512, U512);
|
||||
signed_impls!(I448, U448);
|
||||
cmp_impls!(I448);
|
||||
shift_impls!(I448, U448);
|
||||
subtraction_impls!(I448, I512, U512);
|
||||
mul_impls!(I448, I896);
|
||||
div_impls!(I448, U448);
|
||||
smodinv_impls!(I448, I512);
|
||||
scale_impls!(I448, I512);
|
||||
conversion_impls!(I448, U448, I512, U512);
|
||||
conversion_impls!(I448, U448, I896, U896);
|
||||
conversion_impls!(I448, U448, I960, U960);
|
||||
egcd_impls!(I512, U448, I448, I1024);
|
||||
modinv_impls!(U448, I512, U512);
|
||||
add_impls!(I512, I576, U576);
|
||||
signed_impls!(I512, U512);
|
||||
cmp_impls!(I512);
|
||||
shift_impls!(I512, U512);
|
||||
subtraction_impls!(I512, I576, U576);
|
||||
mul_impls!(I512, I1024);
|
||||
div_impls!(I512, U512);
|
||||
scale_impls!(I512, I576);
|
||||
conversion_impls!(I512, U512, I576, U576);
|
||||
conversion_impls!(I512, U512, I1024, U1024);
|
||||
conversion_impls!(I512, U512, I1088, U1088);
|
||||
egcd_impls!(I576, U512, I512, I1152);
|
||||
modinv_impls!(U512, I576, U576);
|
||||
moddiv_impls!(I576, I1152);
|
||||
add_impls!(I576, I640, U640);
|
||||
signed_impls!(I576, U576);
|
||||
cmp_impls!(I576);
|
||||
shift_impls!(I576, U576);
|
||||
subtraction_impls!(I576, I640, U640);
|
||||
mul_impls!(I576, I1152);
|
||||
div_impls!(I576, U576);
|
||||
smodinv_impls!(I576, I640);
|
||||
scale_impls!(I576, I640);
|
||||
conversion_impls!(I576, U576, I640, U640);
|
||||
conversion_impls!(I576, U576, I1152, U1152);
|
||||
conversion_impls!(I576, U576, I1216, U1216);
|
||||
egcd_impls!(I640, U576, I576, I1280);
|
||||
modinv_impls!(U576, I640, U640);
|
||||
add_impls!(I640, I704, U704);
|
||||
signed_impls!(I640, U640);
|
||||
cmp_impls!(I640);
|
||||
shift_impls!(I640, U640);
|
||||
subtraction_impls!(I640, I704, U704);
|
||||
mul_impls!(I640, I1280);
|
||||
div_impls!(I640, U640);
|
||||
scale_impls!(I640, I704);
|
||||
conversion_impls!(I640, U640, I704, U704);
|
||||
conversion_impls!(I640, U640, I1280, U1280);
|
||||
conversion_impls!(I640, U640, I1344, U1344);
|
||||
signed_impls!(I704, U704);
|
||||
signed_impls!(I768, U768);
|
||||
shift_impls!(I768, U768);
|
||||
subtraction_impls!(I768, I832, U832);
|
||||
mul_impls!(I768, I1536);
|
||||
div_impls!(I768, U768);
|
||||
scale_impls!(I768, I832);
|
||||
conversion_impls!(I768, U768, I832, U832);
|
||||
conversion_impls!(I768, U768, I1536, U1536);
|
||||
moddiv_impls!(I832, I1664);
|
||||
add_impls!(I832, I896, U896);
|
||||
signed_impls!(I832, U832);
|
||||
shift_impls!(I832, U832);
|
||||
mul_impls!(I832, I1664);
|
||||
div_impls!(I832, U832);
|
||||
smodinv_impls!(I832, I896);
|
||||
scale_impls!(I832, I896);
|
||||
conversion_impls!(I832, U832, I896, U896);
|
||||
conversion_impls!(I832, U832, I1664, U1664);
|
||||
egcd_impls!(I896, U832, I832, I1792);
|
||||
modinv_impls!(U832, I896, U896);
|
||||
add_impls!(I896, I960, U960);
|
||||
signed_impls!(I896, U896);
|
||||
cmp_impls!(I896);
|
||||
shift_impls!(I896, U896);
|
||||
subtraction_impls!(I896, I960, U960);
|
||||
mul_impls!(I896, I1792);
|
||||
div_impls!(I896, U896);
|
||||
scale_impls!(I896, I960);
|
||||
conversion_impls!(I896, U896, I960, U960);
|
||||
conversion_impls!(I896, U896, I1792, U1792);
|
||||
conversion_impls!(I896, U896, I1856, U1856);
|
||||
signed_impls!(I960, U960);
|
||||
signed_impls!(I1024, U1024);
|
||||
subtraction_impls!(I1024, I1088, U1088);
|
||||
conversion_impls!(I1024, U1024, I1088, U1088);
|
||||
egcd_impls!(I1088, U1024, I1024, I2176);
|
||||
modinv_impls!(U1024, I1088, U1088);
|
||||
add_impls!(I1088, I1152, U1152);
|
||||
signed_impls!(I1088, U1088);
|
||||
cmp_impls!(I1088);
|
||||
shift_impls!(I1088, U1088);
|
||||
subtraction_impls!(I1088, I1152, U1152);
|
||||
mul_impls!(I1088, I2176);
|
||||
div_impls!(I1088, U1088);
|
||||
scale_impls!(I1088, I1152);
|
||||
conversion_impls!(I1088, U1088, I1152, U1152);
|
||||
conversion_impls!(I1088, U1088, I2176, U2176);
|
||||
conversion_impls!(I1088, U1088, I2240, U2240);
|
||||
signed_impls!(I1152, U1152);
|
||||
shift_impls!(I1152, U1152);
|
||||
subtraction_impls!(I1152, I1216, U1216);
|
||||
mul_impls!(I1152, I2304);
|
||||
div_impls!(I1152, U1152);
|
||||
scale_impls!(I1152, I1216);
|
||||
conversion_impls!(I1152, U1152, I1216, U1216);
|
||||
conversion_impls!(I1152, U1152, I2304, U2304);
|
||||
moddiv_impls!(I1216, I2432);
|
||||
add_impls!(I1216, I1280, U1280);
|
||||
signed_impls!(I1216, U1216);
|
||||
shift_impls!(I1216, U1216);
|
||||
mul_impls!(I1216, I2432);
|
||||
div_impls!(I1216, U1216);
|
||||
smodinv_impls!(I1216, I1280);
|
||||
scale_impls!(I1216, I1280);
|
||||
conversion_impls!(I1216, U1216, I1280, U1280);
|
||||
conversion_impls!(I1216, U1216, I2432, U2432);
|
||||
egcd_impls!(I1280, U1216, I1216, I2560);
|
||||
modinv_impls!(U1216, I1280, U1280);
|
||||
add_impls!(I1280, I1344, U1344);
|
||||
signed_impls!(I1280, U1280);
|
||||
cmp_impls!(I1280);
|
||||
shift_impls!(I1280, U1280);
|
||||
subtraction_impls!(I1280, I1344, U1344);
|
||||
mul_impls!(I1280, I2560);
|
||||
div_impls!(I1280, U1280);
|
||||
scale_impls!(I1280, I1344);
|
||||
conversion_impls!(I1280, U1280, I1344, U1344);
|
||||
conversion_impls!(I1280, U1280, I2560, U2560);
|
||||
conversion_impls!(I1280, U1280, I2624, U2624);
|
||||
signed_impls!(I1344, U1344);
|
||||
signed_impls!(I1536, U1536);
|
||||
conversion_impls!(I1536, U1536, I1600, U1600);
|
||||
egcd_impls!(I1600, U1536, I1536, I3200);
|
||||
add_impls!(I1600, I1664, U1664);
|
||||
signed_impls!(I1600, U1600);
|
||||
cmp_impls!(I1600);
|
||||
shift_impls!(I1600, U1600);
|
||||
subtraction_impls!(I1600, I1664, U1664);
|
||||
mul_impls!(I1600, I3200);
|
||||
div_impls!(I1600, U1600);
|
||||
scale_impls!(I1600, I1664);
|
||||
conversion_impls!(I1600, U1600, I1664, U1664);
|
||||
conversion_impls!(I1600, U1600, I3200, U3200);
|
||||
conversion_impls!(I1600, U1600, I3264, U3264);
|
||||
signed_impls!(I1664, U1664);
|
||||
div_impls!(I1664, U1664);
|
||||
signed_impls!(I1792, U1792);
|
||||
subtraction_impls!(I1792, I1856, U1856);
|
||||
conversion_impls!(I1792, U1792, I1856, U1856);
|
||||
signed_impls!(I1856, U1856);
|
||||
signed_impls!(I2048, U2048);
|
||||
conversion_impls!(I2048, U2048, I2112, U2112);
|
||||
egcd_impls!(I2112, U2048, I2048, I4224);
|
||||
modinv_impls!(U2048, I2112, U2112);
|
||||
add_impls!(I2112, I2176, U2176);
|
||||
signed_impls!(I2112, U2112);
|
||||
cmp_impls!(I2112);
|
||||
shift_impls!(I2112, U2112);
|
||||
subtraction_impls!(I2112, I2176, U2176);
|
||||
mul_impls!(I2112, I4224);
|
||||
div_impls!(I2112, U2112);
|
||||
scale_impls!(I2112, I2176);
|
||||
conversion_impls!(I2112, U2112, I2176, U2176);
|
||||
conversion_impls!(I2112, U2112, I4224, U4224);
|
||||
conversion_impls!(I2112, U2112, I4288, U4288);
|
||||
signed_impls!(I2176, U2176);
|
||||
subtraction_impls!(I2176, I2240, U2240);
|
||||
conversion_impls!(I2176, U2176, I2240, U2240);
|
||||
signed_impls!(I2240, U2240);
|
||||
signed_impls!(I2304, U2304);
|
||||
signed_impls!(I2432, U2432);
|
||||
div_impls!(I2432, U2432);
|
||||
signed_impls!(I2560, U2560);
|
||||
subtraction_impls!(I2560, I2624, U2624);
|
||||
conversion_impls!(I2560, U2560, I2624, U2624);
|
||||
signed_impls!(I2624, U2624);
|
||||
signed_impls!(I3072, U3072);
|
||||
conversion_impls!(I3072, U3072, I3136, U3136);
|
||||
egcd_impls!(I3136, U3072, I3072, I6272);
|
||||
modinv_impls!(U3072, I3136, U3136);
|
||||
add_impls!(I3136, I3200, U3200);
|
||||
signed_impls!(I3136, U3136);
|
||||
cmp_impls!(I3136);
|
||||
shift_impls!(I3136, U3136);
|
||||
subtraction_impls!(I3136, I3200, U3200);
|
||||
mul_impls!(I3136, I6272);
|
||||
div_impls!(I3136, U3136);
|
||||
scale_impls!(I3136, I3200);
|
||||
conversion_impls!(I3136, U3136, I3200, U3200);
|
||||
conversion_impls!(I3136, U3136, I6272, U6272);
|
||||
conversion_impls!(I3136, U3136, I6336, U6336);
|
||||
signed_impls!(I3200, U3200);
|
||||
subtraction_impls!(I3200, I3264, U3264);
|
||||
conversion_impls!(I3200, U3200, I3264, U3264);
|
||||
signed_impls!(I3264, U3264);
|
||||
signed_impls!(I4096, U4096);
|
||||
conversion_impls!(I4096, U4096, I4160, U4160);
|
||||
egcd_impls!(I4160, U4096, I4096, I8320);
|
||||
modinv_impls!(U4096, I4160, U4160);
|
||||
add_impls!(I4160, I4224, U4224);
|
||||
signed_impls!(I4160, U4160);
|
||||
cmp_impls!(I4160);
|
||||
shift_impls!(I4160, U4160);
|
||||
subtraction_impls!(I4160, I4224, U4224);
|
||||
mul_impls!(I4160, I8320);
|
||||
div_impls!(I4160, U4160);
|
||||
scale_impls!(I4160, I4224);
|
||||
conversion_impls!(I4160, U4160, I4224, U4224);
|
||||
conversion_impls!(I4160, U4160, I8320, U8320);
|
||||
conversion_impls!(I4160, U4160, I8384, U8384);
|
||||
signed_impls!(I4224, U4224);
|
||||
subtraction_impls!(I4224, I4288, U4288);
|
||||
conversion_impls!(I4224, U4224, I4288, U4288);
|
||||
signed_impls!(I4288, U4288);
|
||||
signed_impls!(I6272, U6272);
|
||||
subtraction_impls!(I6272, I6336, U6336);
|
||||
conversion_impls!(I6272, U6272, I6336, U6336);
|
||||
signed_impls!(I6336, U6336);
|
||||
signed_impls!(I7680, U7680);
|
||||
conversion_impls!(I7680, U7680, I7744, U7744);
|
||||
egcd_impls!(I7744, U7680, I7680, I15488);
|
||||
add_impls!(I7744, I7808, U7808);
|
||||
signed_impls!(I7744, U7744);
|
||||
cmp_impls!(I7744);
|
||||
shift_impls!(I7744, U7744);
|
||||
subtraction_impls!(I7744, I7808, U7808);
|
||||
mul_impls!(I7744, I15488);
|
||||
div_impls!(I7744, U7744);
|
||||
scale_impls!(I7744, I7808);
|
||||
conversion_impls!(I7744, U7744, I7808, U7808);
|
||||
conversion_impls!(I7744, U7744, I15488, U15488);
|
||||
conversion_impls!(I7744, U7744, I15552, U15552);
|
||||
signed_impls!(I7808, U7808);
|
||||
signed_impls!(I8192, U8192);
|
||||
conversion_impls!(I8192, U8192, I8256, U8256);
|
||||
egcd_impls!(I8256, U8192, I8192, I16512);
|
||||
modinv_impls!(U8192, I8256, U8256);
|
||||
add_impls!(I8256, I8320, U8320);
|
||||
signed_impls!(I8256, U8256);
|
||||
cmp_impls!(I8256);
|
||||
shift_impls!(I8256, U8256);
|
||||
subtraction_impls!(I8256, I8320, U8320);
|
||||
mul_impls!(I8256, I16512);
|
||||
div_impls!(I8256, U8256);
|
||||
scale_impls!(I8256, I8320);
|
||||
conversion_impls!(I8256, U8256, I8320, U8320);
|
||||
conversion_impls!(I8256, U8256, I16512, U16512);
|
||||
conversion_impls!(I8256, U8256, I16576, U16576);
|
||||
signed_impls!(I8320, U8320);
|
||||
subtraction_impls!(I8320, I8384, U8384);
|
||||
conversion_impls!(I8320, U8320, I8384, U8384);
|
||||
signed_impls!(I8384, U8384);
|
||||
signed_impls!(I15360, U15360);
|
||||
conversion_impls!(I15360, U15360, I15424, U15424);
|
||||
egcd_impls!(I15424, U15360, I15360, I30848);
|
||||
modinv_impls!(U15360, I15424, U15424);
|
||||
add_impls!(I15424, I15488, U15488);
|
||||
signed_impls!(I15424, U15424);
|
||||
cmp_impls!(I15424);
|
||||
shift_impls!(I15424, U15424);
|
||||
subtraction_impls!(I15424, I15488, U15488);
|
||||
mul_impls!(I15424, I30848);
|
||||
div_impls!(I15424, U15424);
|
||||
scale_impls!(I15424, I15488);
|
||||
conversion_impls!(I15424, U15424, I15488, U15488);
|
||||
conversion_impls!(I15424, U15424, I30848, U30848);
|
||||
conversion_impls!(I15424, U15424, I30912, U30912);
|
||||
signed_impls!(I15488, U15488);
|
||||
subtraction_impls!(I15488, I15552, U15552);
|
||||
conversion_impls!(I15488, U15488, I15552, U15552);
|
||||
signed_impls!(I15552, U15552);
|
||||
signed_impls!(I16512, U16512);
|
||||
subtraction_impls!(I16512, I16576, U16576);
|
||||
conversion_impls!(I16512, U16512, I16576, U16576);
|
||||
signed_impls!(I16576, U16576);
|
||||
signed_impls!(I30848, U30848);
|
||||
subtraction_impls!(I30848, I30912, U30912);
|
||||
conversion_impls!(I30848, U30848, I30912, U30912);
|
||||
signed_impls!(I30912, U30912);
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
mod sigadd {
|
||||
use super::super::*;
|
||||
use testing::{build_test_path,run_test};
|
||||
|
||||
generate_sigadd_tests!(I256, U256, i256, I320, U320);
|
||||
generate_sigadd_tests!(I320, U320, i320, I384, U384);
|
||||
generate_sigadd_tests!(I448, U448, i448, I512, U512);
|
||||
generate_sigadd_tests!(I512, U512, i512, I576, U576);
|
||||
generate_sigadd_tests!(I576, U576, i576, I640, U640);
|
||||
generate_sigadd_tests!(I640, U640, i640, I704, U704);
|
||||
generate_sigadd_tests!(I832, U832, i832, I896, U896);
|
||||
generate_sigadd_tests!(I896, U896, i896, I960, U960);
|
||||
generate_sigadd_tests!(I1088, U1088, i1088, I1152, U1152);
|
||||
generate_sigadd_tests!(I1216, U1216, i1216, I1280, U1280);
|
||||
generate_sigadd_tests!(I1280, U1280, i1280, I1344, U1344);
|
||||
generate_sigadd_tests!(I1600, U1600, i1600, I1664, U1664);
|
||||
generate_sigadd_tests!(I2112, U2112, i2112, I2176, U2176);
|
||||
generate_sigadd_tests!(I3136, U3136, i3136, I3200, U3200);
|
||||
generate_sigadd_tests!(I4160, U4160, i4160, I4224, U4224);
|
||||
generate_sigadd_tests!(I7744, U7744, i7744, I7808, U7808);
|
||||
generate_sigadd_tests!(I8256, U8256, i8256, I8320, U8320);
|
||||
generate_sigadd_tests!(I15424, U15424, i15424, I15488, U15488);
|
||||
}
|
||||
mod sigsub {
|
||||
use super::super::*;
|
||||
use testing::{build_test_path,run_test};
|
||||
|
||||
generate_sigsub_tests!(I192, U192, i192, I256, U256);
|
||||
generate_sigsub_tests!(I256, U256, i256, I320, U320);
|
||||
generate_sigsub_tests!(I320, U320, i320, I384, U384);
|
||||
generate_sigsub_tests!(I384, U384, i384, I448, U448);
|
||||
generate_sigsub_tests!(I448, U448, i448, I512, U512);
|
||||
generate_sigsub_tests!(I512, U512, i512, I576, U576);
|
||||
generate_sigsub_tests!(I576, U576, i576, I640, U640);
|
||||
generate_sigsub_tests!(I640, U640, i640, I704, U704);
|
||||
generate_sigsub_tests!(I768, U768, i768, I832, U832);
|
||||
generate_sigsub_tests!(I896, U896, i896, I960, U960);
|
||||
generate_sigsub_tests!(I1024, U1024, i1024, I1088, U1088);
|
||||
generate_sigsub_tests!(I1088, U1088, i1088, I1152, U1152);
|
||||
generate_sigsub_tests!(I1152, U1152, i1152, I1216, U1216);
|
||||
generate_sigsub_tests!(I1280, U1280, i1280, I1344, U1344);
|
||||
generate_sigsub_tests!(I1600, U1600, i1600, I1664, U1664);
|
||||
generate_sigsub_tests!(I1792, U1792, i1792, I1856, U1856);
|
||||
generate_sigsub_tests!(I2112, U2112, i2112, I2176, U2176);
|
||||
generate_sigsub_tests!(I2176, U2176, i2176, I2240, U2240);
|
||||
generate_sigsub_tests!(I2560, U2560, i2560, I2624, U2624);
|
||||
generate_sigsub_tests!(I3136, U3136, i3136, I3200, U3200);
|
||||
generate_sigsub_tests!(I3200, U3200, i3200, I3264, U3264);
|
||||
generate_sigsub_tests!(I4160, U4160, i4160, I4224, U4224);
|
||||
generate_sigsub_tests!(I4224, U4224, i4224, I4288, U4288);
|
||||
generate_sigsub_tests!(I6272, U6272, i6272, I6336, U6336);
|
||||
generate_sigsub_tests!(I7744, U7744, i7744, I7808, U7808);
|
||||
generate_sigsub_tests!(I8256, U8256, i8256, I8320, U8320);
|
||||
generate_sigsub_tests!(I8320, U8320, i8320, I8384, U8384);
|
||||
generate_sigsub_tests!(I15424, U15424, i15424, I15488, U15488);
|
||||
generate_sigsub_tests!(I15488, U15488, i15488, I15552, U15552);
|
||||
generate_sigsub_tests!(ignore I16512, U16512, i16512, I16576, U16576);
|
||||
generate_sigsub_tests!(ignore I30848, U30848, i30848, I30912, U30912);
|
||||
}
|
||||
mod signed {
|
||||
use super::super::*;
|
||||
use testing::{build_test_path,run_test};
|
||||
|
||||
generate_signed_tests!(I192, U192, i192);
|
||||
generate_signed_tests!(I256, U256, i256);
|
||||
generate_signed_tests!(I320, U320, i320);
|
||||
generate_signed_tests!(I384, U384, i384);
|
||||
generate_signed_tests!(I448, U448, i448);
|
||||
generate_signed_tests!(I512, U512, i512);
|
||||
generate_signed_tests!(I576, U576, i576);
|
||||
generate_signed_tests!(I640, U640, i640);
|
||||
generate_signed_tests!(I704, U704, i704);
|
||||
generate_signed_tests!(I768, U768, i768);
|
||||
generate_signed_tests!(I832, U832, i832);
|
||||
generate_signed_tests!(I896, U896, i896);
|
||||
generate_signed_tests!(I960, U960, i960);
|
||||
generate_signed_tests!(I1024, U1024, i1024);
|
||||
generate_signed_tests!(I1088, U1088, i1088);
|
||||
generate_signed_tests!(I1152, U1152, i1152);
|
||||
generate_signed_tests!(I1216, U1216, i1216);
|
||||
generate_signed_tests!(I1280, U1280, i1280);
|
||||
generate_signed_tests!(I1344, U1344, i1344);
|
||||
generate_signed_tests!(I1536, U1536, i1536);
|
||||
generate_signed_tests!(I1600, U1600, i1600);
|
||||
generate_signed_tests!(I1664, U1664, i1664);
|
||||
generate_signed_tests!(I1792, U1792, i1792);
|
||||
generate_signed_tests!(I1856, U1856, i1856);
|
||||
generate_signed_tests!(I2048, U2048, i2048);
|
||||
generate_signed_tests!(I2112, U2112, i2112);
|
||||
generate_signed_tests!(I2176, U2176, i2176);
|
||||
generate_signed_tests!(I2240, U2240, i2240);
|
||||
generate_signed_tests!(I2304, U2304, i2304);
|
||||
generate_signed_tests!(I2432, U2432, i2432);
|
||||
generate_signed_tests!(I2560, U2560, i2560);
|
||||
generate_signed_tests!(I2624, U2624, i2624);
|
||||
generate_signed_tests!(I3072, U3072, i3072);
|
||||
generate_signed_tests!(I3136, U3136, i3136);
|
||||
generate_signed_tests!(I3200, U3200, i3200);
|
||||
generate_signed_tests!(I3264, U3264, i3264);
|
||||
generate_signed_tests!(I4096, U4096, i4096);
|
||||
generate_signed_tests!(I4160, U4160, i4160);
|
||||
generate_signed_tests!(I4224, U4224, i4224);
|
||||
generate_signed_tests!(I4288, U4288, i4288);
|
||||
generate_signed_tests!(I6272, U6272, i6272);
|
||||
generate_signed_tests!(I6336, U6336, i6336);
|
||||
generate_signed_tests!(I7680, U7680, i7680);
|
||||
generate_signed_tests!(I7744, U7744, i7744);
|
||||
generate_signed_tests!(I7808, U7808, i7808);
|
||||
generate_signed_tests!(I8192, U8192, i8192);
|
||||
generate_signed_tests!(I8256, U8256, i8256);
|
||||
generate_signed_tests!(I8320, U8320, i8320);
|
||||
generate_signed_tests!(I8384, U8384, i8384);
|
||||
generate_signed_tests!(I15360, U15360, i15360);
|
||||
generate_signed_tests!(I15424, U15424, i15424);
|
||||
generate_signed_tests!(I15488, U15488, i15488);
|
||||
generate_signed_tests!(I15552, U15552, i15552);
|
||||
generate_signed_tests!(I16512, U16512, i16512);
|
||||
generate_signed_tests!(I16576, U16576, i16576);
|
||||
generate_signed_tests!(I30848, U30848, i30848);
|
||||
generate_signed_tests!(I30912, U30912, i30912);
|
||||
}
|
||||
mod sigconversion {
|
||||
generate_sigconversion_tests!(I192, U192, i192);
|
||||
generate_sigconversion_tests!(I256, U256, i256);
|
||||
generate_sigconversion_tests!(I320, U320, i320);
|
||||
generate_sigconversion_tests!(I384, U384, i384);
|
||||
generate_sigconversion_tests!(I448, U448, i448);
|
||||
generate_sigconversion_tests!(I512, U512, i512);
|
||||
generate_sigconversion_tests!(I576, U576, i576);
|
||||
generate_sigconversion_tests!(I640, U640, i640);
|
||||
generate_sigconversion_tests!(I704, U704, i704);
|
||||
generate_sigconversion_tests!(I768, U768, i768);
|
||||
generate_sigconversion_tests!(I832, U832, i832);
|
||||
generate_sigconversion_tests!(I896, U896, i896);
|
||||
generate_sigconversion_tests!(I960, U960, i960);
|
||||
generate_sigconversion_tests!(I1024, U1024, i1024);
|
||||
generate_sigconversion_tests!(I1088, U1088, i1088);
|
||||
generate_sigconversion_tests!(I1152, U1152, i1152);
|
||||
generate_sigconversion_tests!(I1216, U1216, i1216);
|
||||
generate_sigconversion_tests!(I1280, U1280, i1280);
|
||||
generate_sigconversion_tests!(I1344, U1344, i1344);
|
||||
generate_sigconversion_tests!(I1536, U1536, i1536);
|
||||
generate_sigconversion_tests!(I1600, U1600, i1600);
|
||||
generate_sigconversion_tests!(I1664, U1664, i1664);
|
||||
generate_sigconversion_tests!(I1792, U1792, i1792);
|
||||
generate_sigconversion_tests!(I1856, U1856, i1856);
|
||||
generate_sigconversion_tests!(I2048, U2048, i2048);
|
||||
generate_sigconversion_tests!(I2112, U2112, i2112);
|
||||
generate_sigconversion_tests!(I2176, U2176, i2176);
|
||||
generate_sigconversion_tests!(I2240, U2240, i2240);
|
||||
generate_sigconversion_tests!(I2304, U2304, i2304);
|
||||
generate_sigconversion_tests!(I2432, U2432, i2432);
|
||||
generate_sigconversion_tests!(I2560, U2560, i2560);
|
||||
generate_sigconversion_tests!(I2624, U2624, i2624);
|
||||
generate_sigconversion_tests!(I3072, U3072, i3072);
|
||||
generate_sigconversion_tests!(I3136, U3136, i3136);
|
||||
generate_sigconversion_tests!(I3200, U3200, i3200);
|
||||
generate_sigconversion_tests!(I3264, U3264, i3264);
|
||||
generate_sigconversion_tests!(I4096, U4096, i4096);
|
||||
generate_sigconversion_tests!(I4160, U4160, i4160);
|
||||
generate_sigconversion_tests!(I4224, U4224, i4224);
|
||||
generate_sigconversion_tests!(I4288, U4288, i4288);
|
||||
generate_sigconversion_tests!(I6272, U6272, i6272);
|
||||
generate_sigconversion_tests!(I6336, U6336, i6336);
|
||||
generate_sigconversion_tests!(I7680, U7680, i7680);
|
||||
generate_sigconversion_tests!(I7744, U7744, i7744);
|
||||
generate_sigconversion_tests!(I7808, U7808, i7808);
|
||||
generate_sigconversion_tests!(I8192, U8192, i8192);
|
||||
generate_sigconversion_tests!(I8256, U8256, i8256);
|
||||
generate_sigconversion_tests!(I8320, U8320, i8320);
|
||||
generate_sigconversion_tests!(I8384, U8384, i8384);
|
||||
generate_sigconversion_tests!(I15360, U15360, i15360);
|
||||
generate_sigconversion_tests!(I15424, U15424, i15424);
|
||||
generate_sigconversion_tests!(I15488, U15488, i15488);
|
||||
generate_sigconversion_tests!(I15552, U15552, i15552);
|
||||
generate_sigconversion_tests!(I16512, U16512, i16512);
|
||||
generate_sigconversion_tests!(I16576, U16576, i16576);
|
||||
generate_sigconversion_tests!(I30848, U30848, i30848);
|
||||
generate_sigconversion_tests!(I30912, U30912, i30912);
|
||||
}
|
||||
mod sigcmp {
|
||||
use super::super::*;
|
||||
use testing::{build_test_path,run_test};
|
||||
|
||||
generate_sigcmp_tests!(I256, U256, i256);
|
||||
generate_sigcmp_tests!(I320, U320, i320);
|
||||
generate_sigcmp_tests!(I448, U448, i448);
|
||||
generate_sigcmp_tests!(I512, U512, i512);
|
||||
generate_sigcmp_tests!(I576, U576, i576);
|
||||
generate_sigcmp_tests!(I640, U640, i640);
|
||||
generate_sigcmp_tests!(I896, U896, i896);
|
||||
generate_sigcmp_tests!(I1088, U1088, i1088);
|
||||
generate_sigcmp_tests!(I1280, U1280, i1280);
|
||||
generate_sigcmp_tests!(I1600, U1600, i1600);
|
||||
generate_sigcmp_tests!(I2112, U2112, i2112);
|
||||
generate_sigcmp_tests!(I3136, U3136, i3136);
|
||||
generate_sigcmp_tests!(I4160, U4160, i4160);
|
||||
generate_sigcmp_tests!(I7744, U7744, i7744);
|
||||
generate_sigcmp_tests!(I8256, U8256, i8256);
|
||||
generate_sigcmp_tests!(I15424, U15424, i15424);
|
||||
}
|
||||
mod sigmul {
|
||||
use super::super::*;
|
||||
use testing::{build_test_path,run_test};
|
||||
|
||||
generate_sigmul_tests!(I192, U192, i192, I384, U384);
|
||||
generate_sigmul_tests!(I256, U256, i256, I512, U512);
|
||||
generate_sigmul_tests!(I320, U320, i320, I640, U640);
|
||||
generate_sigmul_tests!(I384, U384, i384, I768, U768);
|
||||
generate_sigmul_tests!(I448, U448, i448, I896, U896);
|
||||
generate_sigmul_tests!(I512, U512, i512, I1024, U1024);
|
||||
generate_sigmul_tests!(I576, U576, i576, I1152, U1152);
|
||||
generate_sigmul_tests!(I640, U640, i640, I1280, U1280);
|
||||
generate_sigmul_tests!(I768, U768, i768, I1536, U1536);
|
||||
generate_sigmul_tests!(I832, U832, i832, I1664, U1664);
|
||||
generate_sigmul_tests!(I896, U896, i896, I1792, U1792);
|
||||
generate_sigmul_tests!(I1088, U1088, i1088, I2176, U2176);
|
||||
generate_sigmul_tests!(I1152, U1152, i1152, I2304, U2304);
|
||||
generate_sigmul_tests!(I1216, U1216, i1216, I2432, U2432);
|
||||
generate_sigmul_tests!(I1280, U1280, i1280, I2560, U2560);
|
||||
generate_sigmul_tests!(I1600, U1600, i1600, I3200, U3200);
|
||||
generate_sigmul_tests!(I2112, U2112, i2112, I4224, U4224);
|
||||
generate_sigmul_tests!(I3136, U3136, i3136, I6272, U6272);
|
||||
generate_sigmul_tests!(I4160, U4160, i4160, I8320, U8320);
|
||||
generate_sigmul_tests!(I7744, U7744, i7744, I15488, U15488);
|
||||
generate_sigmul_tests!(I8256, U8256, i8256, I16512, U16512);
|
||||
generate_sigmul_tests!(ignore I15424, U15424, i15424, I30848, U30848);
|
||||
}
|
||||
mod sigdiv {
|
||||
use super::super::*;
|
||||
use testing::{build_test_path,run_test};
|
||||
|
||||
generate_sigdiv_tests!(I192, U192, i192);
|
||||
generate_sigdiv_tests!(I256, U256, i256);
|
||||
generate_sigdiv_tests!(I320, U320, i320);
|
||||
generate_sigdiv_tests!(I384, U384, i384);
|
||||
generate_sigdiv_tests!(I448, U448, i448);
|
||||
generate_sigdiv_tests!(I512, U512, i512);
|
||||
generate_sigdiv_tests!(I576, U576, i576);
|
||||
generate_sigdiv_tests!(I640, U640, i640);
|
||||
generate_sigdiv_tests!(I768, U768, i768);
|
||||
generate_sigdiv_tests!(I832, U832, i832);
|
||||
generate_sigdiv_tests!(I896, U896, i896);
|
||||
generate_sigdiv_tests!(I1088, U1088, i1088);
|
||||
generate_sigdiv_tests!(I1152, U1152, i1152);
|
||||
generate_sigdiv_tests!(I1216, U1216, i1216);
|
||||
generate_sigdiv_tests!(I1280, U1280, i1280);
|
||||
generate_sigdiv_tests!(I1600, U1600, i1600);
|
||||
generate_sigdiv_tests!(I1664, U1664, i1664);
|
||||
generate_sigdiv_tests!(ignore I2112, U2112, i2112);
|
||||
generate_sigdiv_tests!(ignore I2432, U2432, i2432);
|
||||
generate_sigdiv_tests!(ignore I3136, U3136, i3136);
|
||||
generate_sigdiv_tests!(ignore I4160, U4160, i4160);
|
||||
generate_sigdiv_tests!(ignore I7744, U7744, i7744);
|
||||
generate_sigdiv_tests!(ignore I8256, U8256, i8256);
|
||||
generate_sigdiv_tests!(ignore I15424, U15424, i15424);
|
||||
}
|
||||
mod sigshiftl {
|
||||
use super::super::*;
|
||||
use testing::{build_test_path,run_test};
|
||||
|
||||
generate_sigshiftl_tests!(I256, U256, i256);
|
||||
generate_sigshiftl_tests!(I320, U320, i320);
|
||||
generate_sigshiftl_tests!(I384, U384, i384);
|
||||
generate_sigshiftl_tests!(I448, U448, i448);
|
||||
generate_sigshiftl_tests!(I512, U512, i512);
|
||||
generate_sigshiftl_tests!(I576, U576, i576);
|
||||
generate_sigshiftl_tests!(I640, U640, i640);
|
||||
generate_sigshiftl_tests!(I768, U768, i768);
|
||||
generate_sigshiftl_tests!(I832, U832, i832);
|
||||
generate_sigshiftl_tests!(I896, U896, i896);
|
||||
generate_sigshiftl_tests!(I1088, U1088, i1088);
|
||||
generate_sigshiftl_tests!(I1152, U1152, i1152);
|
||||
generate_sigshiftl_tests!(I1216, U1216, i1216);
|
||||
generate_sigshiftl_tests!(I1280, U1280, i1280);
|
||||
generate_sigshiftl_tests!(I1600, U1600, i1600);
|
||||
generate_sigshiftl_tests!(I2112, U2112, i2112);
|
||||
generate_sigshiftl_tests!(I3136, U3136, i3136);
|
||||
generate_sigshiftl_tests!(I4160, U4160, i4160);
|
||||
generate_sigshiftl_tests!(I7744, U7744, i7744);
|
||||
generate_sigshiftl_tests!(I8256, U8256, i8256);
|
||||
generate_sigshiftl_tests!(I15424, U15424, i15424);
|
||||
}
|
||||
mod sigshiftr {
|
||||
use super::super::*;
|
||||
use testing::{build_test_path,run_test};
|
||||
|
||||
generate_sigshiftr_tests!(I256, U256, i256);
|
||||
generate_sigshiftr_tests!(I320, U320, i320);
|
||||
generate_sigshiftr_tests!(I384, U384, i384);
|
||||
generate_sigshiftr_tests!(I448, U448, i448);
|
||||
generate_sigshiftr_tests!(I512, U512, i512);
|
||||
generate_sigshiftr_tests!(I576, U576, i576);
|
||||
generate_sigshiftr_tests!(I640, U640, i640);
|
||||
generate_sigshiftr_tests!(I768, U768, i768);
|
||||
generate_sigshiftr_tests!(I832, U832, i832);
|
||||
generate_sigshiftr_tests!(I896, U896, i896);
|
||||
generate_sigshiftr_tests!(I1088, U1088, i1088);
|
||||
generate_sigshiftr_tests!(I1152, U1152, i1152);
|
||||
generate_sigshiftr_tests!(I1216, U1216, i1216);
|
||||
generate_sigshiftr_tests!(I1280, U1280, i1280);
|
||||
generate_sigshiftr_tests!(I1600, U1600, i1600);
|
||||
generate_sigshiftr_tests!(I2112, U2112, i2112);
|
||||
generate_sigshiftr_tests!(I3136, U3136, i3136);
|
||||
generate_sigshiftr_tests!(I4160, U4160, i4160);
|
||||
generate_sigshiftr_tests!(I7744, U7744, i7744);
|
||||
generate_sigshiftr_tests!(I8256, U8256, i8256);
|
||||
generate_sigshiftr_tests!(I15424, U15424, i15424);
|
||||
}
|
||||
mod sigscale {
|
||||
use super::super::*;
|
||||
use testing::{build_test_path,run_test};
|
||||
|
||||
generate_sigscale_tests!(I192, U192, i192, I256, U256);
|
||||
generate_sigscale_tests!(I256, U256, i256, I320, U320);
|
||||
generate_sigscale_tests!(I320, U320, i320, I384, U384);
|
||||
generate_sigscale_tests!(I384, U384, i384, I448, U448);
|
||||
generate_sigscale_tests!(I448, U448, i448, I512, U512);
|
||||
generate_sigscale_tests!(I512, U512, i512, I576, U576);
|
||||
generate_sigscale_tests!(I576, U576, i576, I640, U640);
|
||||
generate_sigscale_tests!(I640, U640, i640, I704, U704);
|
||||
generate_sigscale_tests!(I768, U768, i768, I832, U832);
|
||||
generate_sigscale_tests!(I832, U832, i832, I896, U896);
|
||||
generate_sigscale_tests!(I896, U896, i896, I960, U960);
|
||||
generate_sigscale_tests!(I1088, U1088, i1088, I1152, U1152);
|
||||
generate_sigscale_tests!(I1152, U1152, i1152, I1216, U1216);
|
||||
generate_sigscale_tests!(I1216, U1216, i1216, I1280, U1280);
|
||||
generate_sigscale_tests!(I1280, U1280, i1280, I1344, U1344);
|
||||
generate_sigscale_tests!(I1600, U1600, i1600, I1664, U1664);
|
||||
generate_sigscale_tests!(I2112, U2112, i2112, I2176, U2176);
|
||||
generate_sigscale_tests!(I3136, U3136, i3136, I3200, U3200);
|
||||
generate_sigscale_tests!(I4160, U4160, i4160, I4224, U4224);
|
||||
generate_sigscale_tests!(I7744, U7744, i7744, I7808, U7808);
|
||||
generate_sigscale_tests!(I8256, U8256, i8256, I8320, U8320);
|
||||
generate_sigscale_tests!(I15424, U15424, i15424, I15488, U15488);
|
||||
}
|
||||
mod egcd {
|
||||
use super::super::*;
|
||||
use testing::{build_test_path,run_test};
|
||||
|
||||
generate_egcd_tests!(I192, U192, i192, I256, U256);
|
||||
generate_egcd_tests!(I256, U256, i256, I320, U320);
|
||||
generate_egcd_tests!(I384, U384, i384, I448, U448);
|
||||
generate_egcd_tests!(I448, U448, i448, I512, U512);
|
||||
generate_egcd_tests!(I512, U512, i512, I576, U576);
|
||||
generate_egcd_tests!(I576, U576, i576, I640, U640);
|
||||
generate_egcd_tests!(I832, U832, i832, I896, U896);
|
||||
generate_egcd_tests!(ignore I1024, U1024, i1024, I1088, U1088);
|
||||
generate_egcd_tests!(ignore I1216, U1216, i1216, I1280, U1280);
|
||||
generate_egcd_tests!(ignore I1536, U1536, i1536, I1600, U1600);
|
||||
generate_egcd_tests!(ignore I2048, U2048, i2048, I2112, U2112);
|
||||
generate_egcd_tests!(ignore I3072, U3072, i3072, I3136, U3136);
|
||||
generate_egcd_tests!(ignore I4096, U4096, i4096, I4160, U4160);
|
||||
generate_egcd_tests!(ignore I7680, U7680, i7680, I7744, U7744);
|
||||
generate_egcd_tests!(ignore I8192, U8192, i8192, I8256, U8256);
|
||||
generate_egcd_tests!(ignore I15360, U15360, i15360, I15424, U15424);
|
||||
}
|
||||
mod moddiv {
|
||||
use super::super::*;
|
||||
use testing::{build_test_path,run_test};
|
||||
|
||||
generate_moddiv_tests!(I192, U192, i192);
|
||||
generate_moddiv_tests!(I256, U256, i256);
|
||||
generate_moddiv_tests!(I384, U384, i384);
|
||||
generate_moddiv_tests!(I448, U448, i448);
|
||||
generate_moddiv_tests!(I576, U576, i576);
|
||||
generate_moddiv_tests!(I832, U832, i832);
|
||||
generate_moddiv_tests!(I1216, U1216, i1216);
|
||||
}
|
||||
mod modinv {
|
||||
use super::super::*;
|
||||
use testing::{build_test_path,run_test};
|
||||
|
||||
generate_modinv_tests!(I192, U192, i192);
|
||||
generate_modinv_tests!(I256, U256, i256);
|
||||
generate_modinv_tests!(I384, U384, i384);
|
||||
generate_modinv_tests!(I448, U448, i448);
|
||||
generate_modinv_tests!(I512, U512, i512);
|
||||
generate_modinv_tests!(I576, U576, i576);
|
||||
generate_modinv_tests!(I832, U832, i832);
|
||||
generate_modinv_tests!(I1024, U1024, i1024);
|
||||
generate_modinv_tests!(I1216, U1216, i1216);
|
||||
generate_modinv_tests!(ignore I2048, U2048, i2048);
|
||||
generate_modinv_tests!(ignore I3072, U3072, i3072);
|
||||
generate_modinv_tests!(ignore I4096, U4096, i4096);
|
||||
generate_modinv_tests!(ignore I8192, U8192, i8192);
|
||||
generate_modinv_tests!(ignore I15360, U15360, i15360);
|
||||
}
|
||||
mod smodinv {
|
||||
use super::super::*;
|
||||
use testing::{build_test_path,run_test};
|
||||
|
||||
generate_smodinv_tests!(I192, U192, i192);
|
||||
generate_smodinv_tests!(I256, U256, i256);
|
||||
generate_smodinv_tests!(I384, U384, i384);
|
||||
generate_smodinv_tests!(I448, U448, i448);
|
||||
generate_smodinv_tests!(I576, U576, i576);
|
||||
generate_smodinv_tests!(I832, U832, i832);
|
||||
generate_smodinv_tests!(I1216, U1216, i1216);
|
||||
}
|
||||
}
|
||||
52
old/signed/mod.rs
Normal file
52
old/signed/mod.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
//! This module includes a large number of signed integer types for very
|
||||
//! large integers, designed to try to match good performance with a high
|
||||
//! assurance threshold.
|
||||
//!
|
||||
//! The types provided in this module, and the functions available for each
|
||||
//! of those types, is derived from standard bit widths for RSA, DSA, and
|
||||
//! Elliptic Curve encryption schemes. If this library does not include a
|
||||
//! function you would like for another cryptographic scheme, please reach
|
||||
//! out to the authors; in many cases, the relevant code can be automatically
|
||||
//! generated.
|
||||
//!
|
||||
#[macro_use]
|
||||
mod add;
|
||||
#[macro_use]
|
||||
mod base;
|
||||
#[macro_use]
|
||||
mod compare;
|
||||
#[macro_use]
|
||||
mod conversion;
|
||||
#[macro_use]
|
||||
mod div;
|
||||
#[macro_use]
|
||||
mod egcd;
|
||||
#[macro_use]
|
||||
mod moddiv;
|
||||
#[macro_use]
|
||||
mod modinv;
|
||||
#[macro_use]
|
||||
mod mul;
|
||||
#[macro_use]
|
||||
mod scale;
|
||||
#[macro_use]
|
||||
mod shift;
|
||||
#[macro_use]
|
||||
mod subtraction;
|
||||
|
||||
use quickcheck::{Arbitrary,Gen};
|
||||
use std::cmp::{Ord,Ordering,PartialOrd};
|
||||
use std::fmt;
|
||||
use std::ops::{Add,AddAssign};
|
||||
use std::ops::{Div,DivAssign};
|
||||
use std::ops::{Mul,MulAssign};
|
||||
use std::ops::{Rem,RemAssign};
|
||||
use std::ops::{Shl,ShlAssign,Shr,ShrAssign};
|
||||
use std::ops::{Sub,SubAssign};
|
||||
use unsigned::*;
|
||||
|
||||
pub use self::egcd::EGCD;
|
||||
pub use self::moddiv::ModDiv;
|
||||
pub use self::modinv::ModInv;
|
||||
|
||||
include!("invoc.rs");
|
||||
54
old/signed/moddiv.rs
Normal file
54
old/signed/moddiv.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
/// Computations of the modular inverse.
|
||||
pub trait ModDiv: Sized {
|
||||
/// Compute the modular division of the number by the given number and
|
||||
/// modulus. The divisor *must* have a modular inverse for this function
|
||||
/// to succeed.
|
||||
fn moddiv(&self, divisor: &Self, phi: &Self) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! moddiv_impls {
|
||||
($sname: ident, $dbl: ident) => {
|
||||
impl ModDiv for $sname {
|
||||
fn moddiv(&self, divisor: &Self, phi: &Self) -> Self
|
||||
{
|
||||
let safe_divisor = divisor % phi;
|
||||
let i = safe_divisor.modinv(&phi).expect("no modular inverse of moddiv divisor");
|
||||
let selfi = i * self;
|
||||
$sname::from( selfi % $dbl::from(phi) )
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_moddiv_tests {
|
||||
($sname: ident, $tname: ident, $mname: ident) => {
|
||||
#[test]
|
||||
fn $mname() {
|
||||
generate_moddiv_tests!(body $sname, $tname, $mname);
|
||||
}
|
||||
};
|
||||
(ignore $sname: ident, $tname: ident, $mname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $mname() {
|
||||
generate_moddiv_tests!(body $sname, $tname, $mname);
|
||||
}
|
||||
};
|
||||
(body $sname: ident, $tname: ident, $mname: ident) => {
|
||||
let fname = build_test_path("moddiv", stringify!($sname));
|
||||
run_test(fname.to_string(), 4, |case| {
|
||||
let (nega, abytes) = case.get("a").unwrap();
|
||||
let (negb, bbytes) = case.get("b").unwrap();
|
||||
let (negm, mbytes) = case.get("m").unwrap();
|
||||
let (negc, cbytes) = case.get("c").unwrap();
|
||||
|
||||
let a = $sname::new(*nega, $tname::from_bytes(abytes));
|
||||
let b = $sname::new(*negb, $tname::from_bytes(bbytes));
|
||||
let m = $sname::new(*negm, $tname::from_bytes(mbytes));
|
||||
let c = $sname::new(*negc, $tname::from_bytes(cbytes));
|
||||
let res = a.moddiv(&b, &m);
|
||||
assert_eq!(c, res);
|
||||
});
|
||||
};
|
||||
}
|
||||
135
old/signed/modinv.rs
Normal file
135
old/signed/modinv.rs
Normal file
@@ -0,0 +1,135 @@
|
||||
/// Computations of the modular inverse.
|
||||
pub trait ModInv: Sized {
|
||||
/// Compute the modular inverse of this number under the given
|
||||
/// modulus, if it exists. If self is a, the modulus / argument
|
||||
/// is phi, and the result is Some(m), then (a * m) % phi = 1.
|
||||
fn modinv(&self, phi: &Self) -> Option<Self>;
|
||||
}
|
||||
|
||||
macro_rules! smodinv_impls {
|
||||
($name: ident, $bigger: ident) => {
|
||||
impl ModInv for $name {
|
||||
fn modinv(&self, phi: &$name) -> Option<$name>
|
||||
{
|
||||
let (_, mut b, g) = phi.egcd(&self);
|
||||
|
||||
if g != $bigger::from(1u64) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let bigphi = $bigger::from(phi);
|
||||
|
||||
while b.is_negative() {
|
||||
b += &bigphi;
|
||||
}
|
||||
|
||||
if b > bigphi {
|
||||
b -= &bigphi;
|
||||
}
|
||||
|
||||
Some($name::from(b))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! modinv_impls {
|
||||
($name: ident, $sname: ident, $uname: ident) => {
|
||||
impl ModInv for $name {
|
||||
fn modinv(&self, phi: &$name) -> Option<$name>
|
||||
{
|
||||
let (_, mut b, g) = phi.egcd(&self);
|
||||
|
||||
if g != $sname::from(1i64) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let sphi = $sname::from($uname::from(phi));
|
||||
|
||||
while b.is_negative() {
|
||||
b += &sphi;
|
||||
}
|
||||
|
||||
if b > sphi {
|
||||
b -= &sphi;
|
||||
}
|
||||
|
||||
Some($name::from($uname::from(b)))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_modinv_tests {
|
||||
($sname: ident, $tname: ident, $mname: ident) => {
|
||||
#[test]
|
||||
fn $mname() {
|
||||
generate_modinv_tests!(body $sname, $tname, $mname);
|
||||
}
|
||||
};
|
||||
(ignore $sname: ident, $tname: ident, $mname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $mname() {
|
||||
generate_modinv_tests!(body $sname, $tname, $mname);
|
||||
}
|
||||
};
|
||||
(body $sname: ident, $tname: ident, $mname: ident) => {
|
||||
let fname = build_test_path("modinv", stringify!($sname));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (nega, abytes) = case.get("a").unwrap();
|
||||
let (negb, bbytes) = case.get("b").unwrap();
|
||||
let (negc, cbytes) = case.get("c").unwrap();
|
||||
|
||||
assert!(!nega && !negb && !negc);
|
||||
let a = $tname::from_bytes(abytes);
|
||||
let b = $tname::from_bytes(bbytes);
|
||||
let c = $tname::from_bytes(cbytes);
|
||||
|
||||
match a.modinv(&b) {
|
||||
None => assert!(false),
|
||||
Some(myc) => {
|
||||
assert_eq!(c, myc);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_smodinv_tests {
|
||||
($sname: ident, $tname: ident, $mname: ident) => {
|
||||
#[test]
|
||||
fn $mname() {
|
||||
generate_smodinv_tests!(body $sname, $tname, $mname);
|
||||
}
|
||||
};
|
||||
(ignore $sname: ident, $tname: ident, $mname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $mname() {
|
||||
generate_smodinv_tests!(body $sname, $tname, $mname);
|
||||
}
|
||||
};
|
||||
(body $sname: ident, $tname: ident, $mname: ident) => {
|
||||
let fname = build_test_path("modinv", stringify!($sname));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (nega, abytes) = case.get("a").unwrap();
|
||||
let (negb, bbytes) = case.get("b").unwrap();
|
||||
let (negc, cbytes) = case.get("c").unwrap();
|
||||
|
||||
assert!(!negb && !negc);
|
||||
let a = $sname::new(*nega, $tname::from_bytes(abytes));
|
||||
let b = $sname::new(false, $tname::from_bytes(bbytes));
|
||||
let c = $sname::new(false, $tname::from_bytes(cbytes));
|
||||
|
||||
match a.modinv(&b) {
|
||||
None => assert!(false),
|
||||
Some(myc) => {
|
||||
assert_eq!(c, myc);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
96
old/signed/mul.rs
Normal file
96
old/signed/mul.rs
Normal file
@@ -0,0 +1,96 @@
|
||||
macro_rules! mul_impls
|
||||
{
|
||||
($name: ident, $dbl: ident) => {
|
||||
impl MulAssign<$name> for $name {
|
||||
fn mul_assign(&mut self, rhs: $name) {
|
||||
self.mul_assign(&rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MulAssign<&'a $name> for $name {
|
||||
fn mul_assign(&mut self, rhs: &$name) {
|
||||
self.value *= &rhs.value;
|
||||
self.negative = !self.value.is_zero() && (self.negative != rhs.negative);
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<$name> for $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: $name) -> $dbl
|
||||
{
|
||||
&self * &rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<&'a $name> for $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: &$name) -> $dbl
|
||||
{
|
||||
&self * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<$name> for &'a $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: $name) -> $dbl
|
||||
{
|
||||
self * &rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> Mul<&'a $name> for &'b $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: &$name) -> $dbl
|
||||
{
|
||||
let outval = &self.value * &rhs.value;
|
||||
let zero = outval.is_zero();
|
||||
$dbl {
|
||||
value: outval,
|
||||
negative: !zero && (self.negative != rhs.negative)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Square<$dbl> for $name {
|
||||
fn square(&self) -> $dbl {
|
||||
$dbl{ negative: false, value: self.value.square() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_sigmul_tests {
|
||||
($sname: ident, $name: ident, $lname: ident, $dbl: ident, $udbl: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_sigmul_tests!(body $sname, $name, $dbl, $udbl);
|
||||
}
|
||||
};
|
||||
(ignore $sname: ident, $name: ident, $lname: ident, $dbl: ident, $udbl: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_sigmul_tests!(body $sname, $name, $dbl, $udbl);
|
||||
}
|
||||
};
|
||||
(body $sname: ident, $name: ident, $dbl: ident, $udbl: ident) => {
|
||||
let fname = build_test_path("sigmul", stringify!($sname));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (nega, abytes) = case.get("a").unwrap();
|
||||
let (negb, bbytes) = case.get("b").unwrap();
|
||||
let (negc, cbytes) = case.get("c").unwrap();
|
||||
|
||||
let mut a = $sname::new(*nega, $name::from_bytes(abytes));
|
||||
let b = $sname::new(*negb, $name::from_bytes(bbytes));
|
||||
let c = $dbl::new(*negc, $udbl::from_bytes(cbytes));
|
||||
assert_eq!(c, &a * &b, "base mul");
|
||||
a *= b;
|
||||
assert_eq!($sname::from(c), a, "in-place mul");
|
||||
});
|
||||
};
|
||||
}
|
||||
121
old/signed/scale.rs
Normal file
121
old/signed/scale.rs
Normal file
@@ -0,0 +1,121 @@
|
||||
macro_rules! scale_impls
|
||||
{
|
||||
($base: ident, $big: ident) => {
|
||||
scale_impls!($base, $big, u8);
|
||||
scale_impls!($base, $big, u16);
|
||||
scale_impls!($base, $big, u32);
|
||||
scale_impls!($base, $big, u64);
|
||||
scale_impls!($base, $big, usize);
|
||||
|
||||
scale_impls!($base, $big, scaled i8);
|
||||
scale_impls!($base, $big, scaled i16);
|
||||
scale_impls!($base, $big, scaled i32);
|
||||
scale_impls!($base, $big, scaled i64);
|
||||
scale_impls!($base, $big, scaled isize);
|
||||
};
|
||||
($base: ident, $big: ident, $prim: ident) => {
|
||||
impl Mul<$prim> for $base {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, factor: $prim) -> $big {
|
||||
&self * factor
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<$prim> for &'a $base {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, factor: $prim) -> $big {
|
||||
let mut res = $big::zero();
|
||||
scale(&mut res.value.value, &self.value.value, factor as u64);
|
||||
res.negative = self.negative && !res.value.is_zero();
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<$base> for $prim {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, rhs: $base) -> $big {
|
||||
rhs.mul(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<&'a $base> for $prim {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, rhs: &$base) -> $big {
|
||||
rhs.mul(self)
|
||||
}
|
||||
}
|
||||
};
|
||||
($base: ident, $big: ident, scaled $prim: ident) => {
|
||||
impl Mul<$prim> for $base {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, factor: $prim) -> $big {
|
||||
&self * factor
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<$prim> for &'a $base {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, factor: $prim) -> $big {
|
||||
let mut res = $big::zero();
|
||||
scale(&mut res.value.value, &self.value.value, factor.abs() as u64);
|
||||
res.negative = (self.negative ^ (factor < 0)) && !res.value.is_zero();
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<$base> for $prim {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, rhs: $base) -> $big {
|
||||
rhs.mul(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<&'a $base> for $prim {
|
||||
type Output = $big;
|
||||
|
||||
fn mul(self, rhs: &$base) -> $big {
|
||||
rhs.mul(self)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_sigscale_tests
|
||||
{
|
||||
($name: ident, $uname: ident, $lname: ident, $big: ident, $ubig: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_sigscale_tests!(body $name, $uname, $lname, $big, $ubig);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $uname:ident, $lname: ident, $big: ident, $ubig: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_sigscale_tests!(body $name, $uname, $lname, $big, $ubig);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $uname: ident, $lname: ident, $big: ident, $ubig: ident) => {
|
||||
let fname = build_test_path("sigscale", stringify!($name));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (nega, abytes) = case.get("a").unwrap();
|
||||
let (negb, bbytes) = case.get("b").unwrap();
|
||||
let (negc, cbytes) = case.get("c").unwrap();
|
||||
|
||||
let a = $name::new(*nega, $uname::from_bytes(abytes));
|
||||
let bbig = $name::new(*negb, $uname::from_bytes(bbytes));
|
||||
let c = $big::new(*negc, $ubig::from_bytes(cbytes));
|
||||
let b = i64::from(&bbig);
|
||||
let res = &a * b;
|
||||
assert_eq!(c, res);
|
||||
});
|
||||
};
|
||||
}
|
||||
135
old/signed/shift.rs
Normal file
135
old/signed/shift.rs
Normal file
@@ -0,0 +1,135 @@
|
||||
|
||||
macro_rules! shift_impls
|
||||
{
|
||||
($sname: ident, $name: ident) => {
|
||||
impl ShlAssign<usize> for $sname {
|
||||
fn shl_assign(&mut self, amt: usize) {
|
||||
self.value <<= amt;
|
||||
if self.value.is_zero() {
|
||||
self.negative = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Shl<usize> for $sname {
|
||||
type Output = $sname;
|
||||
|
||||
fn shl(mut self, amt: usize) -> $sname {
|
||||
self <<= amt;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Shl<usize> for &'a $sname {
|
||||
type Output = $sname;
|
||||
|
||||
fn shl(self, amt: usize) -> $sname {
|
||||
let mut res = self.clone();
|
||||
res <<= amt;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl ShrAssign<usize> for $sname {
|
||||
fn shr_assign(&mut self, amt: usize) {
|
||||
// arithmatic right shift is normal right shift, but always rounding
|
||||
// to negative infinity. To implement this, we first shift right by
|
||||
// rhs bits, and then shift that value back left rhs bits. If the two
|
||||
// are the same, we just cleared out even bits, and there's no rounding
|
||||
// to worry about. If they aren't the same, then we add one back.
|
||||
let original = self.value.clone();
|
||||
self.value >>= amt;
|
||||
if self.negative {
|
||||
let review = self.value.clone() << amt;
|
||||
if review != original {
|
||||
self.value += $name::from(1u64);
|
||||
}
|
||||
}
|
||||
if self.value.is_zero() {
|
||||
self.negative = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Shr<usize> for $sname {
|
||||
type Output = $sname;
|
||||
|
||||
fn shr(mut self, amt: usize) -> $sname {
|
||||
self >>= amt;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Shr<usize> for &'a $sname {
|
||||
type Output = $sname;
|
||||
|
||||
fn shr(self, amt: usize) -> $sname {
|
||||
let mut res = self.clone();
|
||||
res >>= amt;
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_sigshiftl_tests {
|
||||
($sname: ident, $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_sigshiftl_tests!(body $sname, $name, $lname);
|
||||
}
|
||||
};
|
||||
(ignore $sname: ident, $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_sigshiftl_tests!(body $sname, $name, $lname);
|
||||
}
|
||||
};
|
||||
(body $sname: ident, $name: ident, $lname: ident) => {
|
||||
let fname = build_test_path("sigshiftl", stringify!($sname));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (nega, abytes) = case.get("a").unwrap();
|
||||
let (neg1, lbytes) = case.get("l").unwrap();
|
||||
let (negr, rbytes) = case.get("r").unwrap();
|
||||
assert!(!neg1);
|
||||
|
||||
let a = $sname::new(*nega, $name::from_bytes(abytes));
|
||||
let l = $name::from_bytes(lbytes);
|
||||
let r = $sname::new(*negr, $name::from_bytes(rbytes));
|
||||
assert_eq!(r, a << usize::from(l));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_sigshiftr_tests {
|
||||
($sname: ident, $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_sigshiftr_tests!(body $sname, $name, $lname);
|
||||
}
|
||||
};
|
||||
(ignore $sname: ident, $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_sigshiftr_tests!(body $sname, $name, $lname);
|
||||
}
|
||||
};
|
||||
(body $sname: ident, $name: ident, $lname: ident) => {
|
||||
let fname = build_test_path("sigshiftr", stringify!($sname));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (nega, abytes) = case.get("a").unwrap();
|
||||
let (neg1, lbytes) = case.get("l").unwrap();
|
||||
let (negr, rbytes) = case.get("r").unwrap();
|
||||
assert!(!neg1);
|
||||
|
||||
let a = $sname::new(*nega, $name::from_bytes(abytes));
|
||||
let l = $name::from_bytes(lbytes);
|
||||
let r = $sname::new(*negr, $name::from_bytes(rbytes));
|
||||
assert_eq!(r, a >> usize::from(l));
|
||||
});
|
||||
};
|
||||
}
|
||||
113
old/signed/subtraction.rs
Normal file
113
old/signed/subtraction.rs
Normal file
@@ -0,0 +1,113 @@
|
||||
macro_rules! subtraction_impls
|
||||
{
|
||||
($name: ident, $bigger: ident, $ubigger: ident) => {
|
||||
impl SubAssign<$name> for $name {
|
||||
fn sub_assign(&mut self, rhs: $name) {
|
||||
self.sub_assign(&rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SubAssign<&'a $name> for $name {
|
||||
fn sub_assign(&mut self, rhs: &$name) {
|
||||
if self.negative == rhs.negative {
|
||||
if &self.value >= &rhs.value {
|
||||
self.value -= &rhs.value;
|
||||
} else {
|
||||
self.value = rhs.value.clone() - self.value.clone();
|
||||
self.negative = !self.negative;
|
||||
}
|
||||
} else {
|
||||
unsafe_addition(&mut self.value.value, &rhs.value.value, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<$name> for $name {
|
||||
type Output = $bigger;
|
||||
|
||||
fn sub(self, rhs: $name) -> $bigger
|
||||
{
|
||||
&self - &rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Sub<&'a $name> for $name {
|
||||
type Output = $bigger;
|
||||
|
||||
fn sub(self, rhs: &$name) -> $bigger
|
||||
{
|
||||
&self - rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Sub<$name> for &'a $name {
|
||||
type Output = $bigger;
|
||||
|
||||
fn sub(self, rhs: $name) -> $bigger
|
||||
{
|
||||
self - &rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> Sub<&'a $name> for &'b $name {
|
||||
type Output = $bigger;
|
||||
|
||||
fn sub(self, rhs: &$name) -> $bigger
|
||||
{
|
||||
if self.negative == rhs.negative {
|
||||
if &self.value >= &rhs.value {
|
||||
$bigger {
|
||||
negative: self.negative,
|
||||
value: $ubigger::from(&self.value - &rhs.value)
|
||||
}
|
||||
} else {
|
||||
$bigger {
|
||||
negative: !self.negative,
|
||||
value: $ubigger::from(&rhs.value - &self.value)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$bigger {
|
||||
negative: self.negative,
|
||||
value: &self.value + &rhs.value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_sigsub_tests {
|
||||
($sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_sigsub_tests!(body$sname, $name, $lname, $bigger, $ubigger);
|
||||
}
|
||||
};
|
||||
(ignore $sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_sigsub_tests!(body $sname, $name, $lname, $bigger, $ubigger);
|
||||
}
|
||||
};
|
||||
(body $sname: ident, $name: ident, $lname: ident, $bigger: ident, $ubigger: ident) => {
|
||||
let fname = build_test_path("sigsub", stringify!($sname));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (nega, abytes) = case.get("a").unwrap();
|
||||
let (negb, bbytes) = case.get("b").unwrap();
|
||||
let (negc, cbytes) = case.get("c").unwrap();
|
||||
|
||||
let mut a = $sname::new(*nega, $name::from_bytes(abytes));
|
||||
let b = $sname::new(*negb, $name::from_bytes(bbytes));
|
||||
let c = $bigger::new(*negc, $ubigger::from_bytes(cbytes));
|
||||
assert_eq!(c, &a - &b, "base subtraction");
|
||||
|
||||
if c.value.value[c.value.value.len()-1] == 0 {
|
||||
a -= b;
|
||||
assert_eq!($sname::from(c), a, "in-place subtraction");
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user