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:
2019-07-15 17:39:06 -07:00
parent 666378b14b
commit fa872c951a
46 changed files with 696 additions and 203 deletions

116
old/signed/add.rs Normal file
View 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
View 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
View 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
View 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
View 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
View 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 * &quotient));
s = $sname::from($bigger::from(old_s) - (s * &quotient));
t = $sname::from($bigger::from(old_t) - (t * &quotient));
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←uv, A←AC,B←BD;
// otherwise,v←vu, C←CA, D←DB.
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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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");
}
});
};
}