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:
65
src/lib.rs
65
src/lib.rs
@@ -1,49 +1,24 @@
|
||||
extern crate quickcheck;
|
||||
extern crate rand;
|
||||
|
||||
#![no_std]
|
||||
pub mod signed;
|
||||
pub mod unsigned;
|
||||
#[cfg(test)]
|
||||
pub mod testing;
|
||||
|
||||
#[cfg(test)]
|
||||
mod arithmetic {
|
||||
use super::signed::*;
|
||||
use super::unsigned::*;
|
||||
/// A trait definition for large numbers.
|
||||
pub trait CryptoNum {
|
||||
/// Generate a new value of the given type.
|
||||
fn zero() -> Self;
|
||||
/// Test if the number is zero.
|
||||
fn is_zero(&self) -> bool;
|
||||
/// Test if the number is even.
|
||||
fn is_even(&self) -> bool;
|
||||
/// Test if the number is odd.
|
||||
fn is_odd(&self) -> bool;
|
||||
/// The size of this number in bits.
|
||||
fn bit_length() -> usize;
|
||||
/// Mask off the high parts of the number. In particular, it
|
||||
/// zeros the bits above (len * 64).
|
||||
fn mask(&mut self, len: usize);
|
||||
/// Test if the given bit is zero, where bits are numbered in
|
||||
/// least-significant order (0 is the LSB, etc.).
|
||||
fn testbit(&self, bit: usize) -> bool;
|
||||
}
|
||||
|
||||
quickcheck! {
|
||||
fn commutivity_signed_add(x: I576, y: I576) -> bool {
|
||||
(&x + &y) == (&y + &x)
|
||||
}
|
||||
fn commutivity_unsigned_add(x: U576, y: U576) -> bool {
|
||||
(&x + &y) == (&y + &x)
|
||||
}
|
||||
fn commutivity_unsigned_mul(x: U192, y: U192) -> bool {
|
||||
(&x * &y) == (&y * &x)
|
||||
}
|
||||
|
||||
fn associativity_unsigned_add(x: U192, y: U192, z: U192) -> bool {
|
||||
(U256::from(&x) + (&y + &z)) == ((&x + &y) + U256::from(&z))
|
||||
}
|
||||
fn associativity_unsigned_mul(x: U192, y: U192, z: U192) -> bool {
|
||||
(U384::from(&x) * (&y * &z)) == ((&x * &y) * U384::from(&z))
|
||||
}
|
||||
|
||||
fn identity_signed_add(x: I576) -> bool {
|
||||
(&x + I576::zero()) == I640::from(&x)
|
||||
}
|
||||
fn identity_unsigned_add(x: U576) -> bool {
|
||||
(&x + U576::zero()) == U640::from(&x)
|
||||
}
|
||||
fn identity_unsigned_mul(x: U192) -> bool {
|
||||
(&x * U192::from(1u64)) == U384::from(&x)
|
||||
}
|
||||
|
||||
fn additive_inverse(x: I576) -> bool {
|
||||
(&x + x.negate()) == I640::zero()
|
||||
}
|
||||
fn distribution(x: U192, y: U192, z: U192) -> bool {
|
||||
(U256::from(&x) * (&y + &z)) == U512::from((&x * &y) + (&x * &z))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
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");
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
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");
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
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");
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,226 +0,0 @@
|
||||
/// 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)));
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,740 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
//! 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");
|
||||
@@ -1,54 +0,0 @@
|
||||
/// 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);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/// 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);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
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");
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
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);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
|
||||
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));
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
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");
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
pub fn addition(dest: &mut [u64], src: &[u64])
|
||||
{
|
||||
assert_eq!(dest.len(), src.len() + 1);
|
||||
let mut carry: u128 = 0;
|
||||
|
||||
for i in 0..src.len() {
|
||||
let x128 = dest[i] as u128;
|
||||
let y128 = src[i] as u128;
|
||||
let z128 = x128 + y128 + carry;
|
||||
|
||||
dest[i] = z128 as u64;
|
||||
carry = z128 >> 64;
|
||||
}
|
||||
dest[src.len()] = carry as u64;
|
||||
}
|
||||
|
||||
pub fn unsafe_addition(dest: &mut [u64], src: &[u64], really_unsafe: bool)
|
||||
{
|
||||
assert_eq!(dest.len(), src.len());
|
||||
let mut carry: u128 = 0;
|
||||
|
||||
for i in 0..src.len() {
|
||||
let x128 = dest[i] as u128;
|
||||
let y128 = src[i] as u128;
|
||||
let z128 = x128 + y128 + carry;
|
||||
|
||||
dest[i] = z128 as u64;
|
||||
carry = z128 >> 64;
|
||||
}
|
||||
|
||||
if !really_unsafe {
|
||||
assert_eq!(carry, 0, "Unsafe overflow in AddAssign");
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! addition_impls
|
||||
{
|
||||
($base: ident, $bigger: ident) => {
|
||||
impl AddAssign<$base> for $base {
|
||||
fn add_assign(&mut self, rhs: $base) {
|
||||
unsafe_addition(&mut self.value, &rhs.value, false);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AddAssign<&'a $base> for $base {
|
||||
fn add_assign(&mut self, rhs: &$base) {
|
||||
unsafe_addition(&mut self.value, &rhs.value, false);
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<$base> for $base {
|
||||
type Output = $bigger;
|
||||
|
||||
fn add(self, rhs: $base) -> $bigger
|
||||
{
|
||||
let mut dest = $bigger::zero();
|
||||
&dest.value[0..rhs.value.len()].copy_from_slice(&self.value);
|
||||
addition(&mut dest.value, &rhs.value);
|
||||
dest
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Add<&'a $base> for $base {
|
||||
type Output = $bigger;
|
||||
|
||||
fn add(self, rhs: &$base) -> $bigger
|
||||
{
|
||||
let mut dest = $bigger::zero();
|
||||
&dest.value[0..rhs.value.len()].copy_from_slice(&self.value);
|
||||
addition(&mut dest.value, &rhs.value);
|
||||
dest
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Add<$base> for &'a $base {
|
||||
type Output = $bigger;
|
||||
|
||||
fn add(self, rhs: $base) -> $bigger
|
||||
{
|
||||
let mut dest = $bigger::zero();
|
||||
&dest.value[0..rhs.value.len()].copy_from_slice(&self.value);
|
||||
addition(&mut dest.value, &rhs.value);
|
||||
dest
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> Add<&'a $base> for &'b $base {
|
||||
type Output = $bigger;
|
||||
|
||||
fn add(self, rhs: &$base) -> $bigger
|
||||
{
|
||||
let mut dest = $bigger::zero();
|
||||
&dest.value[0..rhs.value.len()].copy_from_slice(&self.value);
|
||||
addition(&mut dest.value, &rhs.value);
|
||||
dest
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_add_tests {
|
||||
($name: ident, $lname: ident, $plus1: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_add_tests!(body $name, $lname, $plus1);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident, $plus1: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_add_tests!(body $name, $lname, $plus1);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident, $plus1: ident) => {
|
||||
let fname = build_test_path("add", stringify!($name));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (neg0, abytes) = case.get("a").unwrap();
|
||||
let (neg1, bbytes) = case.get("b").unwrap();
|
||||
let (neg2, cbytes) = case.get("c").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2);
|
||||
|
||||
let a = $name::from_bytes(abytes);
|
||||
let b = $name::from_bytes(bbytes);
|
||||
let c = $plus1::from_bytes(cbytes);
|
||||
assert_eq!(c, &a + &b);
|
||||
|
||||
if c.value[c.value.len()-1] == 0 {
|
||||
let mut aprime = a.clone();
|
||||
aprime += b;
|
||||
assert_eq!($name::from(c), aprime);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
macro_rules! barrett_impl {
|
||||
($bar: ident, $name: ident, $name64: ident, $dbl: ident, $dbl64: ident) => {
|
||||
#[derive(Clone,PartialEq)]
|
||||
pub struct $bar {
|
||||
pub(crate) k: usize,
|
||||
pub(crate) m: $name64,
|
||||
pub(crate) mu: $name64
|
||||
}
|
||||
|
||||
impl $bar {
|
||||
/// Generate a new Barrett number from the given input. This operation
|
||||
/// is relatively slow, so you should only do it if you plan to use
|
||||
/// reduce() multiple times with the ame number.
|
||||
pub fn new(m: $name) -> $bar {
|
||||
// Step #1: Figure out k
|
||||
let mut k = 0;
|
||||
for i in 0..m.value.len() {
|
||||
if m.value[i] != 0 {
|
||||
k = i;
|
||||
}
|
||||
}
|
||||
k += 1;
|
||||
// Step #2: Compute b
|
||||
let mut b = $dbl64::zero();
|
||||
b.value[2*k] = 1;
|
||||
// Step #3: Divide b by m.
|
||||
let bigm = $dbl64::from(&m);
|
||||
let quot = b / &bigm;
|
||||
let resm = $name64::from(&m);
|
||||
let mu = $name64::from(");
|
||||
// Done!
|
||||
$bar { k: k, m: resm, mu: mu }
|
||||
}
|
||||
|
||||
/// Generate a new Barrett number from its component parts. You
|
||||
/// probably don't want to use it; it's mostly here for debugging
|
||||
/// purposes, so that tests won't have to compute this all the
|
||||
/// time.
|
||||
pub fn from_components(k: usize, m: $name64, mu: $name64) -> $bar {
|
||||
$bar { k: k, m: m, mu: mu }
|
||||
}
|
||||
|
||||
// Reduce the input by this value; in other words, perform a mod
|
||||
// operation.
|
||||
#[inline(always)]
|
||||
pub fn reduce(&self, x: &$dbl) -> $name {
|
||||
// 1. q1←⌊x/bk−1⌋, q2←q1 · μ, q3←⌊q2/bk+1⌋.
|
||||
let q1: $name64 = $name64::from(x >> ((self.k - 1) * 64));
|
||||
let q2 = q1 * &self.mu;
|
||||
let q3: $name64 = $name64::from(q2 >> ((self.k + 1) * 64));
|
||||
// 2. r1←x mod bk+1, r2←q3 · m mod bk+1, r←r1 − r2.
|
||||
let mut r: $dbl64 = $dbl64::from(x);
|
||||
r.mask(self.k + 1);
|
||||
let mut r2: $dbl64 = $dbl64::from(q3 * &self.m);
|
||||
r2.mask(self.k + 1);
|
||||
let went_negative = &r < &r2;
|
||||
r -= &r2;
|
||||
// 3. If r<0 then r←r+bk+1.
|
||||
if went_negative {
|
||||
let mut bk1 = $dbl64::zero();
|
||||
bk1.value[self.k+1] = 1;
|
||||
// this may overflow, and we should probably be OK with it.
|
||||
r += &bk1;
|
||||
}
|
||||
// 4. While r≥m do: r←r−m.
|
||||
let m2 = $dbl64::from(&self.m);
|
||||
while &r > &m2 {
|
||||
r -= &m2;
|
||||
}
|
||||
// Done!
|
||||
$name::from(&r)
|
||||
}
|
||||
}
|
||||
|
||||
impl $name {
|
||||
/// Generate a Barrett number from this number.
|
||||
pub fn generate_barrett(&self) -> $bar {
|
||||
$bar::new(self.clone())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn new_barrett(k: usize, m: $name64, mu: $name64) -> $bar {
|
||||
$bar{ k: k, m: m, mu: mu }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for $bar {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct(stringify!($name))
|
||||
.field("k", &self.k)
|
||||
.field("m", &self.m)
|
||||
.field("mu", &self.mu)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_barrett_gen_tests {
|
||||
($name: ident, $lname: ident, $bname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_barrett_gen_tests!(body $name, $lname, $bname);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident, $bname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_barrett_gen_tests!(body $name, $lname, $bname);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident, $bname: ident) => {
|
||||
let fname = build_test_path("barrett_gen", stringify!($name));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (neg0, mbytes) = case.get("m").unwrap();
|
||||
let (neg1, kbytes) = case.get("k").unwrap();
|
||||
let (neg2, ubytes) = case.get("u").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2);
|
||||
|
||||
let m = $name::from_bytes(mbytes);
|
||||
let kbig = $name::from_bytes(kbytes);
|
||||
let mu = $bname::from_bytes(ubytes);
|
||||
//
|
||||
let mbig = $bname::from(&m);
|
||||
let k = usize::from(&kbig);
|
||||
//
|
||||
let bar = m.generate_barrett();
|
||||
assert_eq!(k, bar.k);
|
||||
assert_eq!(mbig, bar.m);
|
||||
assert_eq!(mu, bar.mu);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_barrett_red_tests {
|
||||
($name: ident, $lname: ident, $bname: ident, $dbl: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_barrett_red_tests!(body $name, $lname, $bname, $dbl);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident, $bname: ident, $dbl: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_barrett_red_tests!(body $name, $lname, $bname, $dbl);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident, $bname: ident, $dbl: ident) => {
|
||||
let fname = build_test_path("barrett_reduce", stringify!($name));
|
||||
run_test(fname.to_string(), 5, |case| {
|
||||
let (neg0, mbytes) = case.get("m").unwrap();
|
||||
let (neg1, kbytes) = case.get("k").unwrap();
|
||||
let (neg2, ubytes) = case.get("u").unwrap();
|
||||
let (neg3, xbytes) = case.get("x").unwrap();
|
||||
let (neg4, rbytes) = case.get("r").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4);
|
||||
|
||||
let m = $name::from_bytes(mbytes);
|
||||
let kbig = $name::from_bytes(kbytes);
|
||||
let k = usize::from(&kbig);
|
||||
let mu = $bname::from_bytes(ubytes);
|
||||
let bar = $name::new_barrett(usize::from(k), $bname::from(m), mu);
|
||||
let x = $dbl::from_bytes(xbytes);
|
||||
let r = $name::from_bytes(rbytes);
|
||||
//
|
||||
assert_eq!(r, bar.reduce(&x));
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
/// A trait definition for large numbers.
|
||||
pub trait CryptoNum {
|
||||
/// Generate a new value of the given type.
|
||||
fn zero() -> Self;
|
||||
/// Test if the number is zero.
|
||||
fn is_zero(&self) -> bool;
|
||||
/// Test if the number is even.
|
||||
fn is_even(&self) -> bool;
|
||||
/// Test if the number is odd.
|
||||
fn is_odd(&self) -> bool;
|
||||
/// The size of this number in bits.
|
||||
fn bit_length() -> usize;
|
||||
/// Mask off the high parts of the number. In particular, it
|
||||
/// zeros the bits above (len * 64).
|
||||
fn mask(&mut self, len: usize);
|
||||
/// Test if the given bit is zero, where bits are numbered in
|
||||
/// least-significant order (0 is the LSB, etc.).
|
||||
fn testbit(&self, bit: usize) -> bool;
|
||||
}
|
||||
|
||||
macro_rules! generate_base
|
||||
{
|
||||
($name: ident, $size: expr) => {
|
||||
#[derive(Clone)]
|
||||
pub struct $name {
|
||||
pub(crate) value: [u64; $size]
|
||||
}
|
||||
|
||||
impl CryptoNum for $name {
|
||||
fn zero() -> $name {
|
||||
$name{ value: [0; $size] }
|
||||
}
|
||||
|
||||
fn bit_length() -> usize {
|
||||
$size * 64
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool {
|
||||
self.value.iter().all(|&x| x == 0)
|
||||
}
|
||||
|
||||
fn is_even(&self) -> bool {
|
||||
(self.value[0] & 0x1) == 0
|
||||
}
|
||||
|
||||
fn is_odd(&self) -> bool {
|
||||
(self.value[0] & 0x1) == 1
|
||||
}
|
||||
|
||||
fn mask(&mut self, len: usize) {
|
||||
let dellen = min(len, $size);
|
||||
for i in dellen..$size {
|
||||
self.value[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fn testbit(&self, bit: usize) -> bool {
|
||||
let idx = bit / 64;
|
||||
let offset = bit % 64;
|
||||
if idx >= $size {
|
||||
return false;
|
||||
}
|
||||
(self.value[idx] & (1u64 << offset)) != 0
|
||||
}
|
||||
}
|
||||
|
||||
impl Arbitrary for $name {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> $name {
|
||||
let mut res = $name::zero();
|
||||
|
||||
for val in res.value.iter_mut() {
|
||||
*val = g.next_u64();
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for $name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(stringify!($name))?;
|
||||
f.write_str("{")?;
|
||||
f.debug_list().entries(self.value.iter()).finish()?;
|
||||
f.write_str("}")
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u64; $size]> for $name {
|
||||
fn from(x: [u64; $size]) -> $name {
|
||||
$name{ value: x }
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOr for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn bitor(mut self, rhs: Self) -> Self {
|
||||
for (idx, val) in self.value.iter_mut().enumerate() {
|
||||
*val |= rhs.value[idx];
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl BitAnd for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn bitand(mut self, rhs: Self) -> Self {
|
||||
for (idx, val) in self.value.iter_mut().enumerate() {
|
||||
*val &= rhs.value[idx];
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_base_tests
|
||||
{
|
||||
($name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_base_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_base_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident) => {
|
||||
let fname = build_test_path("base", stringify!($name));
|
||||
run_test(fname.to_string(), 8, |case| {
|
||||
let (neg0, xbytes) = case.get("x").unwrap();
|
||||
let (neg1, mbytes) = case.get("m").unwrap();
|
||||
let (neg2, zbytes) = case.get("z").unwrap();
|
||||
let (neg3, ebytes) = case.get("e").unwrap();
|
||||
let (neg4, obytes) = case.get("o").unwrap();
|
||||
let (neg5, rbytes) = case.get("r").unwrap();
|
||||
let (neg6, bbytes) = case.get("b").unwrap();
|
||||
let (neg7, tbytes) = case.get("t").unwrap();
|
||||
assert!(!neg0&&!neg1&&!neg2&&!neg3&&!neg4&&!neg5&&!neg6&&!neg7);
|
||||
let mut x = $name::from_bytes(xbytes);
|
||||
let m = $name::from_bytes(mbytes);
|
||||
let z = 1 == zbytes[0];
|
||||
let e = 1 == ebytes[0];
|
||||
let o = 1 == obytes[0];
|
||||
let r = $name::from_bytes(rbytes);
|
||||
let b = usize::from($name::from_bytes(bbytes));
|
||||
let t = 1 == tbytes[0];
|
||||
assert_eq!(x.is_zero(), z);
|
||||
assert_eq!(x.is_even(), e);
|
||||
assert_eq!(x.is_odd(), o);
|
||||
assert_eq!(x.testbit(b), t);
|
||||
x.mask(usize::from(&m));
|
||||
assert_eq!(x, r);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
use std::cmp::*;
|
||||
|
||||
pub fn compare(a: &[u64], b: &[u64]) -> Ordering {
|
||||
assert_eq!(a.len(), b.len(), "Incompatible numbers in comparison");
|
||||
|
||||
let mut i = (a.len() - 1) as isize;
|
||||
|
||||
while i >= 0 {
|
||||
let iu = i as usize;
|
||||
match a[iu].cmp(&b[iu]) {
|
||||
Ordering::Greater => return Ordering::Greater,
|
||||
Ordering::Less => return Ordering::Less,
|
||||
Ordering::Equal => i -= 1
|
||||
}
|
||||
}
|
||||
|
||||
Ordering::Equal
|
||||
}
|
||||
|
||||
macro_rules! cmp_impls {
|
||||
($name: ident) => {
|
||||
impl PartialEq for $name {
|
||||
fn eq(&self, rhs: &$name) -> bool {
|
||||
compare(&self.value, &rhs.value) == Ordering::Equal
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for $name {}
|
||||
|
||||
impl PartialOrd for $name {
|
||||
fn partial_cmp(&self, rhs: &$name) -> Option<Ordering> {
|
||||
Some(compare(&self.value, &rhs.value))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for $name {
|
||||
fn cmp(&self, rhs: &$name) -> Ordering {
|
||||
compare(&self.value, &rhs.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_cmp_tests {
|
||||
($name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_cmp_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_cmp_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident) => {
|
||||
let fname = build_test_path("cmp", stringify!($name));
|
||||
run_test(fname.to_string(), 5, |case| {
|
||||
let (neg0, abytes) = case.get("a").unwrap();
|
||||
let (neg1, 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!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4);
|
||||
let a = $name::from_bytes(abytes);
|
||||
let b = $name::from_bytes(bbytes);
|
||||
let e = 1 == ebytes[0];
|
||||
let g = 1 == gbytes[0];
|
||||
let l = 1 == lbytes[0];
|
||||
|
||||
assert_eq!(e, a == b);
|
||||
assert_eq!(g, a > b);
|
||||
assert_eq!(l, a < b);
|
||||
|
||||
assert_eq!(e || g, a >= b);
|
||||
assert_eq!(e || l, a <= b);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/// Conversion from bytes into the numeric type.
|
||||
pub trait Decoder {
|
||||
fn from_bytes(x: &[u8]) -> Self;
|
||||
}
|
||||
|
||||
/// Conversion from the numeric types into a byte buffer.
|
||||
pub trait Encoder {
|
||||
fn to_bytes(&self) -> Vec<u8>;
|
||||
}
|
||||
|
||||
pub(crate) fn raw_decoder(input: &[u8], output: &mut [u64])
|
||||
{
|
||||
let mut item = 0;
|
||||
let mut shift = 0;
|
||||
let mut idx = 0;
|
||||
|
||||
for v in input.iter().rev() {
|
||||
item |= (*v as u64) << shift;
|
||||
shift += 8;
|
||||
if shift == 64 {
|
||||
shift = 0;
|
||||
output[idx] = item;
|
||||
idx += 1;
|
||||
item = 0;
|
||||
}
|
||||
}
|
||||
if item != 0 {
|
||||
output[idx] = item;
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! generate_decoder {
|
||||
($name: ident) => {
|
||||
impl Decoder for $name {
|
||||
fn from_bytes(x: &[u8]) -> $name {
|
||||
let mut res = $name::zero();
|
||||
raw_decoder(x, &mut res.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! generate_encoder {
|
||||
($name: ident) => {
|
||||
impl Encoder for $name {
|
||||
fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut res = Vec::with_capacity(self.value.len() * 8);
|
||||
for v in self.value.iter().rev() {
|
||||
let val = *v;
|
||||
res.push( (val >> 56) as u8);
|
||||
res.push( (val >> 48) as u8);
|
||||
res.push( (val >> 40) as u8);
|
||||
res.push( (val >> 32) as u8);
|
||||
res.push( (val >> 24) as u8);
|
||||
res.push( (val >> 16) as u8);
|
||||
res.push( (val >> 8) as u8);
|
||||
res.push( (val >> 0) as u8);
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! generate_codec
|
||||
{
|
||||
($name: ident) => {
|
||||
generate_decoder!($name);
|
||||
generate_encoder!($name);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_codec_tests {
|
||||
($name: ident, $lname: ident) => {
|
||||
#[cfg(test)]
|
||||
mod $lname {
|
||||
use super::super::super::*;
|
||||
|
||||
quickcheck! {
|
||||
fn decode_encode(x: $name) -> bool {
|
||||
let bytes = x.to_bytes();
|
||||
let x2 = $name::from_bytes(&bytes);
|
||||
x == x2
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
macro_rules! generate_base_conversions
|
||||
{
|
||||
($name: ident) => {
|
||||
generate_base_type_convert!($name, u8);
|
||||
generate_base_type_convert!($name, u16);
|
||||
generate_base_type_convert!($name, u32);
|
||||
generate_base_type_convert!($name, u64);
|
||||
generate_base_type_convert!($name, usize);
|
||||
|
||||
impl From<u128> for $name {
|
||||
fn from(x: u128) -> $name {
|
||||
let mut res = $name::zero();
|
||||
res.value[0] = x as u64;
|
||||
res.value[1] = (x >> 64) as u64;
|
||||
res
|
||||
}
|
||||
}
|
||||
};
|
||||
() => {};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_conversion_tests
|
||||
{
|
||||
($name: ident, $lname: ident) => {
|
||||
#[cfg(test)]
|
||||
mod $lname {
|
||||
use super::super::super::*;
|
||||
use std::convert::From;
|
||||
|
||||
quickcheck! {
|
||||
fn conversion_u8( x: u8) -> bool { x == u8::from($name::from(x)) }
|
||||
fn conversion_u16( x: u16) -> bool { x == u16::from($name::from(x)) }
|
||||
fn conversion_u32( x: u32) -> bool { x == u32::from($name::from(x)) }
|
||||
fn conversion_u64( x: u64) -> bool { x == u64::from($name::from(x)) }
|
||||
fn conversion_usize(x: usize) -> bool { x == usize::from($name::from(x)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! conversion_impls
|
||||
{
|
||||
($name: ident, $other: ident) => {
|
||||
impl<'a> From<&'a $other> for $name {
|
||||
fn from(x: &$other) -> $name {
|
||||
let mut res = $name::zero();
|
||||
let len = res.value.len();
|
||||
assert!(x.value.len() > res.value.len());
|
||||
res.value.copy_from_slice(&x.value[0..len]);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a $name> for $other {
|
||||
fn from(x: &$name) -> $other {
|
||||
let mut res = $other::zero();
|
||||
let len = x.value.len();
|
||||
|
||||
assert!(x.value.len() < res.value.len());
|
||||
res.value[0..len].copy_from_slice(&x.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$other> for $name {
|
||||
fn from(x: $other) -> $name {
|
||||
$name::from(&x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$name> for $other {
|
||||
fn from(x: $name) -> $other {
|
||||
$other::from(&x)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! generate_base_type_convert
|
||||
{
|
||||
($name: ident, $base: ident) => {
|
||||
impl From<$base> for $name {
|
||||
fn from(x: $base) -> $name {
|
||||
let mut res = $name::zero();
|
||||
res.value[0] = x as u64;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$name> for $base {
|
||||
fn from(x: $name) -> $base {
|
||||
x.value[0] as $base
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a $name> for $base {
|
||||
fn from(x: &$name) -> $base {
|
||||
x.value[0] as $base
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,293 +0,0 @@
|
||||
/// Concurrent div/mod operations for a number, so that you don't
|
||||
/// have to do them separately.
|
||||
pub trait DivMod
|
||||
where Self: Sized
|
||||
{
|
||||
/// Compute the quotient and remainder of a and b.
|
||||
fn divmod(&self, rhs: &Self) -> (Self, Self);
|
||||
}
|
||||
|
||||
pub fn get_number_size(v: &[u64]) -> Option<usize>
|
||||
{
|
||||
for (idx, val) in v.iter().enumerate().rev() {
|
||||
if *val != 0 {
|
||||
return Some(idx);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
macro_rules! safesubidx
|
||||
{
|
||||
($array: expr, $index: expr, $amt: expr) => ({
|
||||
let idx = $index;
|
||||
let amt = $amt;
|
||||
|
||||
if idx < amt {
|
||||
0
|
||||
} else {
|
||||
$array[idx-amt]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! div_impls
|
||||
{
|
||||
($name: ident, $dbl: ident) => {
|
||||
impl DivMod for $name {
|
||||
fn divmod(&self, rhs: &$name) -> ($name, $name) {
|
||||
// if the divisor is larger, then the answer is pretty simple
|
||||
if rhs > self {
|
||||
return ($name::zero(), self.clone());
|
||||
}
|
||||
// compute the basic number sizes
|
||||
let mut n = match get_number_size(&self.value) {
|
||||
None => 0,
|
||||
Some(v) => v
|
||||
};
|
||||
let t = match get_number_size(&rhs.value) {
|
||||
None => panic!("Division by zero!"),
|
||||
Some(v) => v
|
||||
};
|
||||
assert!(t <= n);
|
||||
// now generate mutable versions we can mess with
|
||||
let mut x = $dbl::from(self);
|
||||
let mut y = $dbl::from(rhs);
|
||||
// If we want this to perform reasonable, it's useful if the
|
||||
// value of y[t] is shifted so that the high bit is set.
|
||||
let lambda_shift = y.value[t].leading_zeros() as usize;
|
||||
if lambda_shift != 0 {
|
||||
let dupx = x.value.clone();
|
||||
let dupy = y.value.clone();
|
||||
|
||||
shiftl(&mut x.value, &dupx, lambda_shift);
|
||||
shiftl(&mut y.value, &dupy, lambda_shift);
|
||||
n = get_number_size(&x.value).unwrap();
|
||||
}
|
||||
// now go!
|
||||
// 1. For j from 0 to (n-t) do: q[j] = 0;
|
||||
// [NB: I take some liberties with this concept]
|
||||
let mut q = $dbl::zero();
|
||||
// 2. While (x >= y * b^(n-t)) do the following:
|
||||
let mut ybnt = $dbl::zero();
|
||||
for i in 0..self.value.len() {
|
||||
ybnt.value[(n-t)+i] = y.value[i];
|
||||
if (n-t)+i >= ybnt.value.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while x > ybnt {
|
||||
q.value[n - t] += 1;
|
||||
x -= &ybnt;
|
||||
}
|
||||
// 3. For i from n down to t+1 do the following:
|
||||
let mut i = n;
|
||||
while i >= (t + 1) {
|
||||
// 3.1. If x[i] = y[t]
|
||||
if x.value[i] == y.value[t] {
|
||||
// ... then set q[i-t-1] = b - 1
|
||||
q.value[i-t-1] = 0xFFFFFFFFFFFFFFFF;
|
||||
} else {
|
||||
// ... otherwise set q[i-t-1] =
|
||||
// floor((x[i] * b + x[i-1]) / y[t])
|
||||
let xib = (x.value[i] as u128) << 64;
|
||||
let xi1 = safesubidx!(x.value,i,1) as u128;
|
||||
let yt = y.value[t] as u128;
|
||||
let qit1 = (xib + xi1) / yt;
|
||||
q.value[i-t-1] = qit1 as u64;
|
||||
}
|
||||
// 3.2. While q[i-t-1] * (y[t]*b + y[t-1]) >
|
||||
// (x[i] * b^2 + x[i-1] * b + x[i-2])
|
||||
loop {
|
||||
// three is very close to 2.
|
||||
let qit1 = U192::from(safesubidx!(q.value,i-t,1));
|
||||
let mut ybits = U192::zero();
|
||||
ybits.value[0] = safesubidx!(y.value, t, 1);
|
||||
ybits.value[1] = y.value[t];
|
||||
let qiybs = &qit1 * &ybits;
|
||||
let mut xbits = U384::zero();
|
||||
xbits.value[0] = safesubidx!(x.value,i,2);
|
||||
xbits.value[1] = safesubidx!(x.value,i,1);
|
||||
xbits.value[2] = x.value[i];
|
||||
|
||||
if !(&qiybs > &xbits) {
|
||||
break;
|
||||
}
|
||||
|
||||
// ... do q[i-t-1] = q[i-t-1] - 1
|
||||
q.value[i-t-1] -= 1;
|
||||
}
|
||||
// 3.3. x = x - q[i-t-1] * y * b^(i-t-1)
|
||||
// 3.4. If x < 0
|
||||
// then set x = x + y * b^(i-t-1) and
|
||||
// q[i-t-1] = q[i-t-1] - 1
|
||||
let mut qbit1 = $name::zero();
|
||||
qbit1.value[i-t-1] = q.value[i-t-1];
|
||||
let smallery = $name::from(&y);
|
||||
let mut subpart = &smallery * &qbit1;
|
||||
if subpart > x {
|
||||
let mut addback = $dbl::zero();
|
||||
for (idx, val) in y.value.iter().enumerate() {
|
||||
let dest = idx + (i - t - 1);
|
||||
if dest < addback.value.len() {
|
||||
addback.value[dest] = *val;
|
||||
}
|
||||
}
|
||||
q.value[i-t-1] -= 1;
|
||||
subpart -= &addback;
|
||||
}
|
||||
assert!(subpart <= x);
|
||||
x -= &subpart;
|
||||
i -= 1;
|
||||
}
|
||||
// 4. r = x ... sort of. Remember, we potentially did a bit of shifting
|
||||
// around at the very beginning, which we now need to account for. On the
|
||||
// bright side, we only need to account for this in the remainder.
|
||||
let mut r = $name::from(&x);
|
||||
let dupr = r.value.clone();
|
||||
shiftr(&mut r.value, &dupr, lambda_shift);
|
||||
// 5. Return (q,r)
|
||||
let resq = $name::from(&q);
|
||||
(resq, r)
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign 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 (res, _) = self.divmod(&rhs);
|
||||
self.value.copy_from_slice(&res.value);
|
||||
}
|
||||
}
|
||||
|
||||
impl Div for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn div(self, rhs: $name) -> $name {
|
||||
let (res, _) = self.divmod(&rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Div<&'a $name> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn div(self, rhs: &$name) -> $name {
|
||||
let (res, _) = self.divmod(rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Div<$name> for &'a $name {
|
||||
type Output = $name;
|
||||
|
||||
fn div(self, rhs: $name) -> $name {
|
||||
let (res, _) = self.divmod(&rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
impl<'a,'b> Div<&'a $name> for &'b $name {
|
||||
type Output = $name;
|
||||
|
||||
fn div(self, rhs: &$name) -> $name {
|
||||
let (res, _) = self.divmod(rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl RemAssign 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) {
|
||||
let (_, res) = self.divmod(rhs);
|
||||
self.value.copy_from_slice(&res.value);
|
||||
}
|
||||
}
|
||||
|
||||
impl Rem for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn rem(self, rhs: $name) -> $name {
|
||||
let (_, res) = self.divmod(&rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Rem<&'a $name> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn rem(self, rhs: &$name) -> $name {
|
||||
let (_, res) = self.divmod(&rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Rem<$name> for &'a $name {
|
||||
type Output = $name;
|
||||
|
||||
fn rem(self, rhs: $name) -> $name {
|
||||
let (_, res) = self.divmod(&rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> Rem<&'a $name> for &'b $name {
|
||||
type Output = $name;
|
||||
|
||||
fn rem(self, rhs: &$name) -> $name {
|
||||
let (_, res) = self.divmod(&rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_div_tests {
|
||||
($name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_div_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_div_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident) => {
|
||||
let fname = build_test_path("div", stringify!($name));
|
||||
run_test(fname.to_string(), 4, |case| {
|
||||
let (neg0, abytes) = case.get("a").unwrap();
|
||||
let (neg1, bbytes) = case.get("b").unwrap();
|
||||
let (neg2, qbytes) = case.get("q").unwrap();
|
||||
let (neg3, rbytes) = case.get("r").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2 && !neg3);
|
||||
|
||||
let a = $name::from_bytes(abytes);
|
||||
let b = $name::from_bytes(bbytes);
|
||||
let q = $name::from_bytes(qbytes);
|
||||
let r = $name::from_bytes(rbytes);
|
||||
let (myq, myr) = a.divmod(&b);
|
||||
assert_eq!(q, myq);
|
||||
assert_eq!(r, myr);
|
||||
let mut a2 = a.clone();
|
||||
a2 /= &b;
|
||||
assert_eq!(a2, q);
|
||||
let mut a3 = a.clone();
|
||||
a3 %= &b;
|
||||
assert_eq!(a3, r);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
macro_rules! generate_formatter {
|
||||
($name: ident) => {
|
||||
impl fmt::UpperHex for $name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for x in self.value.iter().rev() {
|
||||
f.write_char(tochar(true, x >> 60))?;
|
||||
f.write_char(tochar(true, x >> 56))?;
|
||||
f.write_char(tochar(true, x >> 52))?;
|
||||
f.write_char(tochar(true, x >> 48))?;
|
||||
f.write_char(tochar(true, x >> 44))?;
|
||||
f.write_char(tochar(true, x >> 40))?;
|
||||
f.write_char(tochar(true, x >> 36))?;
|
||||
f.write_char(tochar(true, x >> 32))?;
|
||||
f.write_char(tochar(true, x >> 28))?;
|
||||
f.write_char(tochar(true, x >> 24))?;
|
||||
f.write_char(tochar(true, x >> 20))?;
|
||||
f.write_char(tochar(true, x >> 16))?;
|
||||
f.write_char(tochar(true, x >> 12))?;
|
||||
f.write_char(tochar(true, x >> 8))?;
|
||||
f.write_char(tochar(true, x >> 4))?;
|
||||
f.write_char(tochar(true, x >> 0))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::LowerHex for $name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for x in self.value.iter().rev() {
|
||||
f.write_char(tochar(false, x >> 60))?;
|
||||
f.write_char(tochar(false, x >> 56))?;
|
||||
f.write_char(tochar(false, x >> 52))?;
|
||||
f.write_char(tochar(false, x >> 48))?;
|
||||
f.write_char(tochar(false, x >> 44))?;
|
||||
f.write_char(tochar(false, x >> 40))?;
|
||||
f.write_char(tochar(false, x >> 36))?;
|
||||
f.write_char(tochar(false, x >> 32))?;
|
||||
f.write_char(tochar(false, x >> 28))?;
|
||||
f.write_char(tochar(false, x >> 24))?;
|
||||
f.write_char(tochar(false, x >> 20))?;
|
||||
f.write_char(tochar(false, x >> 16))?;
|
||||
f.write_char(tochar(false, x >> 12))?;
|
||||
f.write_char(tochar(false, x >> 8))?;
|
||||
f.write_char(tochar(false, x >> 4))?;
|
||||
f.write_char(tochar(false, x >> 0))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn tochar(upper: bool, val: u64) -> char {
|
||||
match val & 0xF {
|
||||
0x0 => '0',
|
||||
0x1 => '1',
|
||||
0x2 => '2',
|
||||
0x3 => '3',
|
||||
0x4 => '4',
|
||||
0x5 => '5',
|
||||
0x6 => '6',
|
||||
0x7 => '7',
|
||||
0x8 => '8',
|
||||
0x9 => '9',
|
||||
0xA => if upper { 'A' } else { 'a' },
|
||||
0xB => if upper { 'B' } else { 'b' },
|
||||
0xC => if upper { 'C' } else { 'c' },
|
||||
0xD => if upper { 'D' } else { 'd' },
|
||||
0xE => if upper { 'E' } else { 'e' },
|
||||
0xF => if upper { 'F' } else { 'f' },
|
||||
_ => panic!("The world is broken, rejoice, rejoice.")
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,104 +1 @@
|
||||
//! This module includes a large number of unsigned 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.
|
||||
//!
|
||||
//! For performance reasons, we also include support for Barrett reduction,
|
||||
//! which should improve the speed of modular reduction of large numbers for
|
||||
//! those cases in which you will be frequently performing modulo operations
|
||||
//! using the same modulus.
|
||||
#[macro_use]
|
||||
mod add;
|
||||
#[macro_use]
|
||||
mod barrett;
|
||||
#[macro_use]
|
||||
mod base;
|
||||
#[macro_use]
|
||||
mod cmp;
|
||||
#[macro_use]
|
||||
mod codec;
|
||||
#[macro_use]
|
||||
mod conversion;
|
||||
#[macro_use]
|
||||
mod div;
|
||||
#[macro_use]
|
||||
mod formatter;
|
||||
#[macro_use]
|
||||
mod modexp;
|
||||
#[macro_use]
|
||||
mod modmul;
|
||||
#[macro_use]
|
||||
mod modsq;
|
||||
#[macro_use]
|
||||
mod mul;
|
||||
#[macro_use]
|
||||
mod primes;
|
||||
#[macro_use]
|
||||
mod rand;
|
||||
#[macro_use]
|
||||
mod scale;
|
||||
#[macro_use]
|
||||
mod shifts;
|
||||
#[macro_use]
|
||||
mod sqrt;
|
||||
#[macro_use]
|
||||
mod square;
|
||||
#[macro_use]
|
||||
mod sub;
|
||||
|
||||
pub use self::base::CryptoNum;
|
||||
pub use self::codec::{Encoder,Decoder};
|
||||
pub use self::div::DivMod;
|
||||
pub use self::modexp::ModExp;
|
||||
pub use self::modmul::ModMul;
|
||||
pub use self::modsq::ModSquare;
|
||||
pub use self::primes::PrimeGen;
|
||||
pub use self::square::Square;
|
||||
pub use self::sqrt::SquareRoot;
|
||||
|
||||
pub(crate) use self::add::unsafe_addition;
|
||||
pub(crate) use self::scale::scale;
|
||||
|
||||
use rand::{Rng,RngCore};
|
||||
use rand::distributions::{Distribution,Standard};
|
||||
use rand::distributions::uniform::*;
|
||||
use self::add::addition;
|
||||
use self::cmp::compare;
|
||||
use self::codec::raw_decoder;
|
||||
use self::div::get_number_size;
|
||||
use self::formatter::tochar;
|
||||
use self::mul::{multiply,multiply_small};
|
||||
use self::primes::SMALL_PRIMES;
|
||||
use self::shifts::{shiftl,shiftr};
|
||||
use self::sub::subtract;
|
||||
use std::cmp::{Ordering,min};
|
||||
use std::fmt;
|
||||
use std::fmt::Write;
|
||||
use std::ops::{Add,AddAssign};
|
||||
use std::ops::{Mul,MulAssign};
|
||||
use std::ops::{Div,DivAssign};
|
||||
use std::ops::{Rem,RemAssign};
|
||||
use std::ops::{Shl,ShlAssign,Shr,ShrAssign};
|
||||
use std::ops::{Sub,SubAssign};
|
||||
use std::ops::{BitAnd,BitOr};
|
||||
|
||||
use quickcheck::{Arbitrary,Gen};
|
||||
|
||||
macro_rules! base_impls
|
||||
{
|
||||
($name: ident, $size: expr) => {
|
||||
generate_base!($name, $size);
|
||||
generate_base_conversions!($name);
|
||||
generate_codec!($name);
|
||||
generate_formatter!($name);
|
||||
cmp_impls!($name);
|
||||
}
|
||||
}
|
||||
|
||||
include!("invoc.rs");
|
||||
mod u192;
|
||||
@@ -1,116 +0,0 @@
|
||||
/// Modular exponentiation for a value.
|
||||
pub trait ModExp<T> {
|
||||
/// Modular exponentiation using the given modulus type. If it's possible,
|
||||
/// we suggest using Barrett values, which are much faster than doing
|
||||
/// modulo with the number types.
|
||||
fn modexp(&self, e: &Self, m: &T) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! modexp_impls {
|
||||
($name: ident, $other: ident) => {
|
||||
impl ModExp<$other> for $name {
|
||||
fn modexp(&self, ine: &$name, m: &$other) -> $name {
|
||||
// S <- g
|
||||
let mut s = self.clone();
|
||||
// A <- 1
|
||||
let mut a = $name::from(1u64);
|
||||
// We do a quick skim through and find the highest index that
|
||||
// actually has a value in it.
|
||||
let mut e = ine.clone();
|
||||
// While e != 0 do the following:
|
||||
while e.value.iter().any(|x| *x != 0) {
|
||||
// If e is odd then A <- A * S
|
||||
if e.value[0] & 1 != 0 {
|
||||
a = a.modmul(&s, m);
|
||||
}
|
||||
// e <- floor(e / 2)
|
||||
let mut carry = 0;
|
||||
e.value.iter_mut().rev().for_each(|x| {
|
||||
let new_carry = *x & 1;
|
||||
*x = (*x >> 1) | (carry << 63);
|
||||
carry = new_carry;
|
||||
});
|
||||
// If e != 0 then S <- S * S
|
||||
s = s.modsq(m);
|
||||
}
|
||||
// Return A
|
||||
a
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_modexp_tests {
|
||||
($name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_modexp_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_modexp_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident) => {
|
||||
let fname = build_test_path("modexp", stringify!($name));
|
||||
run_test(fname.to_string(), 6, |case| {
|
||||
let (neg0, bbytes) = case.get("b").unwrap();
|
||||
let (neg1, ebytes) = case.get("e").unwrap();
|
||||
let (neg2, mbytes) = case.get("m").unwrap();
|
||||
let (neg3, rbytes) = case.get("r").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2 && !neg3);
|
||||
|
||||
let b = $name::from_bytes(bbytes);
|
||||
let e = $name::from_bytes(ebytes);
|
||||
let m = $name::from_bytes(mbytes);
|
||||
let r = $name::from_bytes(rbytes);
|
||||
assert_eq!(r, b.modexp(&e, &m));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_barrett_modexp_tests {
|
||||
(ignore $name: ident, $lname: ident, $bname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_barrett_modexp_tests!(body $name, $lname, $bname);
|
||||
}
|
||||
};
|
||||
($name: ident, $lname: ident, $bname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_barrett_modexp_tests!(body $name, $lname, $bname);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident, $bname: ident) => {
|
||||
let fname = build_test_path("modexp", stringify!($name));
|
||||
run_test(fname.to_string(), 6, |case| {
|
||||
let (neg0, bbytes) = case.get("b").unwrap();
|
||||
let (neg1, ebytes) = case.get("e").unwrap();
|
||||
let (neg2, mbytes) = case.get("m").unwrap();
|
||||
let (neg3, rbytes) = case.get("r").unwrap();
|
||||
let (neg4, kbytes) = case.get("k").unwrap();
|
||||
let (neg5, ubytes) = case.get("u").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4 && !neg5);
|
||||
|
||||
let b = $name::from_bytes(bbytes);
|
||||
let e = $name::from_bytes(ebytes);
|
||||
let m = $name::from_bytes(mbytes);
|
||||
let r = $name::from_bytes(rbytes);
|
||||
let kbig = $name::from_bytes(kbytes);
|
||||
let k = usize::from(kbig);
|
||||
let mu = $bname::from_bytes(ubytes);
|
||||
let bar = $name::new_barrett(k, $bname::from(m), mu);
|
||||
|
||||
if k == b.value.len() {
|
||||
assert_eq!(r, b.modexp(&e, &bar));
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
/// Modular multiplication of the type.
|
||||
pub trait ModMul<T> {
|
||||
/// Modular multiplication using the given modulus type. If it's possible,
|
||||
/// we suggest using Barrett values, which are much faster than doing
|
||||
/// modulo with the number types.
|
||||
fn modmul(&self, x: &Self, m: &T) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! modmul_impls {
|
||||
($name: ident, $dbl: ident, $barrett: ident) => {
|
||||
impl ModMul<$name> for $name {
|
||||
fn modmul(&self, x: &$name, m: &$name) -> $name {
|
||||
let mulres = (self as &$name) * x;
|
||||
let bigm = $dbl::from(m);
|
||||
let (_, bigres) = mulres.divmod(&bigm);
|
||||
$name::from(bigres)
|
||||
}
|
||||
}
|
||||
|
||||
impl ModMul<$barrett> for $name {
|
||||
fn modmul(&self, x: &$name, m: &$barrett) -> $name {
|
||||
let mulres = (self as &$name) * x;
|
||||
m.reduce(&mulres)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_modmul_tests {
|
||||
($name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_modmul_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_modmul_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident) => {
|
||||
let fname = build_test_path("modmul", stringify!($name));
|
||||
run_test(fname.to_string(), 6, |case| {
|
||||
let (neg0, abytes) = case.get("a").unwrap();
|
||||
let (neg1, bbytes) = case.get("b").unwrap();
|
||||
let (neg2, mbytes) = case.get("m").unwrap();
|
||||
let (neg3, cbytes) = case.get("c").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2 && !neg3);
|
||||
|
||||
let a = $name::from_bytes(abytes);
|
||||
let b = $name::from_bytes(bbytes);
|
||||
let m = $name::from_bytes(mbytes);
|
||||
let c = $name::from_bytes(cbytes);
|
||||
assert_eq!(c, a.modmul(&b, &m));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_barrett_modmul_tests {
|
||||
($name: ident, $lname: ident, $bname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_barrett_modmul_tests!(body $name, $lname, $bname);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident, $bname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_barrett_modmul_tests!(body $name, $lname, $bname);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident, $bname: ident) => {
|
||||
let fname = build_test_path("modmul", stringify!($name));
|
||||
run_test(fname.to_string(), 6, |case| {
|
||||
let (neg0, abytes) = case.get("a").unwrap();
|
||||
let (neg1, bbytes) = case.get("b").unwrap();
|
||||
let (neg2, mbytes) = case.get("m").unwrap();
|
||||
let (neg3, cbytes) = case.get("c").unwrap();
|
||||
let (neg4, kbytes) = case.get("k").unwrap();
|
||||
let (neg5, ubytes) = case.get("u").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4 && !neg5);
|
||||
|
||||
let a = $name::from_bytes(abytes);
|
||||
let b = $name::from_bytes(bbytes);
|
||||
let m = $name::from_bytes(mbytes);
|
||||
let c = $name::from_bytes(cbytes);
|
||||
let kbig = $name::from_bytes(kbytes);
|
||||
let k = usize::from(kbig);
|
||||
let mu = $bname::from_bytes(ubytes);
|
||||
let bar = $name::new_barrett(k, $bname::from(m), mu);
|
||||
|
||||
if k == a.value.len() {
|
||||
assert_eq!(c, a.modmul(&b, &bar));
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/// Modular squaring
|
||||
pub trait ModSquare<T> {
|
||||
/// Modular squaring using the given modulus type. If it's possible,
|
||||
/// we suggest using Barrett values, which are much faster than doing
|
||||
/// modulo with the number types.
|
||||
fn modsq(&self, m: &T) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! modsq_impls {
|
||||
($name: ident, $dbl: ident, $barrett: ident) => {
|
||||
impl ModSquare<$name> for $name {
|
||||
fn modsq(&self, m: &$name) -> $name {
|
||||
let bigsquare = self.square();
|
||||
let bigm = $dbl::from(m);
|
||||
let (_, res) = bigsquare.divmod(&bigm);
|
||||
$name::from(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl ModSquare<$barrett> for $name {
|
||||
fn modsq(&self, m: &$barrett) -> $name {
|
||||
let bigsquare = self.square();
|
||||
m.reduce(&bigsquare)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_modsq_tests {
|
||||
($name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_modsq_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_modsq_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident) => {
|
||||
let fname = build_test_path("modsq", stringify!($name));
|
||||
run_test(fname.to_string(), 5, |case| {
|
||||
let (neg0, abytes) = case.get("a").unwrap();
|
||||
let (neg1, mbytes) = case.get("m").unwrap();
|
||||
let (neg2, cbytes) = case.get("c").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2);
|
||||
|
||||
let a = $name::from_bytes(abytes);
|
||||
let m = $name::from_bytes(mbytes);
|
||||
let c = $name::from_bytes(cbytes);
|
||||
assert_eq!(c, a.modsq(&m));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_barrett_modsq_tests {
|
||||
($name: ident, $lname: ident, $bname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_barrett_modsq_tests!(body $name, $lname, $bname);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident, $bname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_barrett_modsq_tests!(body $name, $lname, $bname);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident, $bname: ident) => {
|
||||
let fname = build_test_path("modsq", stringify!($name));
|
||||
run_test(fname.to_string(), 5, |case| {
|
||||
let (neg0, abytes) = case.get("a").unwrap();
|
||||
let (neg1, mbytes) = case.get("m").unwrap();
|
||||
let (neg2, cbytes) = case.get("c").unwrap();
|
||||
let (neg3, kbytes) = case.get("k").unwrap();
|
||||
let (neg4, ubytes) = case.get("u").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4);
|
||||
|
||||
let a = $name::from_bytes(abytes);
|
||||
let m = $name::from_bytes(mbytes);
|
||||
let c = $name::from_bytes(cbytes);
|
||||
let kbig = $name::from_bytes(kbytes);
|
||||
let k = usize::from(kbig);
|
||||
let mu = $bname::from_bytes(ubytes);
|
||||
let bar = $name::new_barrett(k, $bname::from(m), mu);
|
||||
|
||||
if k == a.value.len() {
|
||||
assert_eq!(c, a.modsq(&bar));
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
pub fn multiply(dest: &mut [u64], left: &[u64], right: &[u64])
|
||||
{
|
||||
let len = right.len();
|
||||
let mut i = 0;
|
||||
|
||||
assert_eq!(left.len(), len, "Uneven argument lengths in multiply");
|
||||
assert_eq!(dest.len(), len*2, "Bad destination size in multiply");
|
||||
|
||||
while i < len {
|
||||
let mut carry = 0;
|
||||
let mut j = 0;
|
||||
|
||||
while j < len {
|
||||
let old = dest[i+j] as u128;
|
||||
let l128 = left[j] as u128;
|
||||
let r128 = right[i] as u128;
|
||||
let uv = old + (l128 * r128) + carry;
|
||||
dest[i+j] = uv as u64;
|
||||
carry = uv >> 64;
|
||||
j += 1;
|
||||
}
|
||||
dest[i+len] = carry as u64;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn multiply_small(dest: &mut [u64], left: &[u64], right: &[u64])
|
||||
{
|
||||
let len = right.len();
|
||||
|
||||
assert_eq!(dest.len(), len);
|
||||
assert_eq!(left.len(), len);
|
||||
for i in 0..len { dest[i] = 0; }
|
||||
for i in 0..len {
|
||||
let mut carry = 0;
|
||||
|
||||
for j in 0..len {
|
||||
if i+j >= len {
|
||||
carry = 0;
|
||||
continue;
|
||||
}
|
||||
let old = dest[i+j] as u128;
|
||||
let l128 = left[j] as u128;
|
||||
let r128 = right[i] as u128;
|
||||
let uv = old + (l128 * r128) + carry;
|
||||
dest[i+j] = uv as u64;
|
||||
carry = uv >> 64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! multiply_impls {
|
||||
($name: ident, $dbl: ident) => {
|
||||
impl Mul<$name> for $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: $name) -> $dbl {
|
||||
let mut res = $dbl::zero();
|
||||
multiply(&mut res.value, &self.value, &rhs.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<$name> for &'a $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: $name) -> $dbl {
|
||||
let mut res = $dbl::zero();
|
||||
multiply(&mut res.value, &self.value, &rhs.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<&'a $name> for $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: &$name) -> $dbl {
|
||||
let mut res = $dbl::zero();
|
||||
multiply(&mut res.value, &self.value, &rhs.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> Mul<&'a $name> for &'b $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: &$name) -> $dbl {
|
||||
let mut res = $dbl::zero();
|
||||
multiply(&mut res.value, &self.value, &rhs.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign for $name {
|
||||
fn mul_assign(&mut self, rhs: $name) {
|
||||
let copy = self.value.clone();
|
||||
multiply_small(&mut self.value, ©, &rhs.value);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MulAssign<&'a $name> for $name {
|
||||
fn mul_assign(&mut self, rhs: &$name) {
|
||||
let copy = self.value.clone();
|
||||
multiply_small(&mut self.value, ©, &rhs.value);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_mul_tests
|
||||
{
|
||||
($name: ident, $lname: ident, $dbl: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_mul_tests!(body $name, $lname, $dbl);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident, $dbl: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_mul_tests!(body $name, $lname, $dbl);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident, $dbl: ident) => {
|
||||
let fname = build_test_path("mul", stringify!($name));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (neg0, abytes) = case.get("a").unwrap();
|
||||
let (neg1, bbytes) = case.get("b").unwrap();
|
||||
let (neg2, cbytes) = case.get("c").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2);
|
||||
|
||||
let mut a = $name::from_bytes(abytes);
|
||||
let b = $name::from_bytes(bbytes);
|
||||
let c = $dbl::from_bytes(cbytes);
|
||||
assert_eq!(c, &a * &b, "standard multiplication");
|
||||
a *= b;
|
||||
assert_eq!($name::from(c), a);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
use rand::RngCore;
|
||||
|
||||
/// Functions related to the generation of random numbers and primes.
|
||||
pub trait PrimeGen: Sized + PartialOrd {
|
||||
/// Generate a random prime number, using the given RNG and running
|
||||
/// the primality check for the given number of iterations. This is
|
||||
/// equivalent to calling `random_primef` with the identity function
|
||||
/// as the modifier.
|
||||
fn random_prime<R: RngCore>(rng: &mut R, iters: usize) -> Self {
|
||||
Self::random_primef(rng, iters, |x| Some(x))
|
||||
}
|
||||
/// Generate a random prime number, using a modification function
|
||||
/// and running the primality check for the given number of iterations.
|
||||
/// The modifier function is run after the routine generates a random
|
||||
/// number, but before the primality check, and can be used to force
|
||||
/// the return value to have certain properties: the low bit set, the
|
||||
/// high bit set, and/or the number is above a certain value.
|
||||
fn random_primef<F,R>(rng: &mut R, iters: usize, prep: F) -> Self
|
||||
where F: Fn(Self) -> Option<Self>, R: RngCore;
|
||||
/// Determine if the given number is probably prime. This should be
|
||||
/// an implementation of Miller-Rabin, with some quick sanity checks,
|
||||
/// over the given number of iterations.
|
||||
fn probably_prime<R: RngCore>(&self, rng: &mut R, iters: usize) -> bool;
|
||||
}
|
||||
|
||||
pub static SMALL_PRIMES: [u64; 310] = [
|
||||
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
|
||||
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
|
||||
73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
|
||||
127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
|
||||
179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
|
||||
233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
|
||||
283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
|
||||
353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
|
||||
419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
|
||||
467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
|
||||
547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
|
||||
607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
|
||||
661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
|
||||
739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
|
||||
811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
|
||||
877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
|
||||
947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013,
|
||||
1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
|
||||
1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
|
||||
1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
|
||||
1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
|
||||
1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
|
||||
1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
|
||||
1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
|
||||
1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583,
|
||||
1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657,
|
||||
1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
|
||||
1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
|
||||
1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,
|
||||
1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
|
||||
1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053];
|
||||
|
||||
macro_rules! prime_gen_impls {
|
||||
($name: ident) => {
|
||||
impl PrimeGen for $name {
|
||||
fn random_primef<F,R>(rng: &mut R, iters: usize, modifier: F) -> Self
|
||||
where
|
||||
F: Fn($name) -> Option<$name>,
|
||||
R: RngCore
|
||||
{
|
||||
loop {
|
||||
let base = rng.gen();
|
||||
|
||||
if let Some(candidate) = modifier(base) {
|
||||
let good = candidate.probably_prime(rng, iters);
|
||||
|
||||
if good {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn probably_prime<R: RngCore>(&self, rng: &mut R, iters: usize) -> bool
|
||||
{
|
||||
for tester in SMALL_PRIMES.iter() {
|
||||
if self.is_multiple_of(*tester) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
self.miller_rabin(rng, iters)
|
||||
}
|
||||
}
|
||||
|
||||
impl $name {
|
||||
fn miller_rabin<R: RngCore>(&self, rng: &mut R, iters: usize) -> bool
|
||||
{
|
||||
let one = $name::from(1u64);
|
||||
let two = $name::from(2u64);
|
||||
let nm1 = self - $name::from(1u64);
|
||||
// Quoth Wikipedia:
|
||||
// write n - 1 as 2^r*d with d odd by factoring powers of 2 from n - 1
|
||||
let mut d = nm1.clone();
|
||||
let mut r = 0;
|
||||
while d.is_even() {
|
||||
d >>= 1;
|
||||
r += 1;
|
||||
assert!(r < $name::bit_length());
|
||||
}
|
||||
// WitnessLoop: repeat k times
|
||||
'WitnessLoop: for _k in 0..iters {
|
||||
// pick a random integer a in the range [2, n - 2]
|
||||
let a = rng.gen_range(&two, &nm1);
|
||||
// x <- a^d mod n
|
||||
let mut x = a.modexp(&d, self);
|
||||
// if x = 1 or x = n - 1 then
|
||||
if (&x == &one) || (&x == &nm1) {
|
||||
// continue WitnessLoop
|
||||
continue 'WitnessLoop;
|
||||
}
|
||||
// repeat r - 1 times:
|
||||
for _i in 0..r {
|
||||
// x <- x^2 mod n
|
||||
x = x.modexp(&two, self);
|
||||
// if x = 1 then
|
||||
if &x == &one {
|
||||
// return composite
|
||||
return false;
|
||||
}
|
||||
// if x = n - 1 then
|
||||
if &x == &nm1 {
|
||||
// continue WitnessLoop
|
||||
continue 'WitnessLoop;
|
||||
}
|
||||
}
|
||||
// return composite
|
||||
return false;
|
||||
}
|
||||
// return probably prime
|
||||
true
|
||||
}
|
||||
|
||||
fn is_multiple_of(&self, x: u64) -> bool
|
||||
{
|
||||
(self % $name::from(x)).is_zero()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
macro_rules! random_impls {
|
||||
($name: ident, $uniform: ident) => {
|
||||
impl Distribution<$name> for Standard {
|
||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $name
|
||||
{
|
||||
let mut res = $name::zero();
|
||||
|
||||
for x in res.value.iter_mut() {
|
||||
*x = rng.next_u64();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
pub struct $uniform {
|
||||
low: $name,
|
||||
high: $name,
|
||||
inclusive: bool
|
||||
}
|
||||
|
||||
impl UniformSampler for $uniform {
|
||||
type X = $name;
|
||||
|
||||
fn new<B1,B2>(low: B1, high: B2) -> Self
|
||||
where B1: SampleBorrow<Self::X> + Sized,
|
||||
B2: SampleBorrow<Self::X> + Sized
|
||||
{
|
||||
$uniform {
|
||||
low: low.borrow().clone(),
|
||||
high: high.borrow().clone(),
|
||||
inclusive: false
|
||||
}
|
||||
}
|
||||
|
||||
fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
|
||||
where B1: SampleBorrow<Self::X> + Sized,
|
||||
B2: SampleBorrow<Self::X> + Sized
|
||||
{
|
||||
$uniform {
|
||||
low: low.borrow().clone(),
|
||||
high: high.borrow().clone(),
|
||||
inclusive: true
|
||||
}
|
||||
}
|
||||
|
||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
|
||||
loop {
|
||||
let candidate = rng.gen();
|
||||
|
||||
if candidate < self.low {
|
||||
continue;
|
||||
}
|
||||
|
||||
if candidate > self.high {
|
||||
continue;
|
||||
}
|
||||
|
||||
if !self.inclusive && (candidate == self.high) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SampleUniform for $name {
|
||||
type Sampler = $uniform;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
pub fn scale(dest: &mut [u64], bignum: &[u64], factor: u64)
|
||||
{
|
||||
let len = bignum.len();
|
||||
let factor128 = factor as u128;
|
||||
let mut carry = 0;
|
||||
|
||||
assert_eq!(dest.len(), len+1, "Bad destination size in scale");
|
||||
for i in 0..len {
|
||||
let digit128 = bignum[i] as u128;
|
||||
let res128 = carry + (digit128 * factor128);
|
||||
dest[i] = res128 as u64;
|
||||
carry = res128 >> 64;
|
||||
}
|
||||
dest[len] = carry as u64;
|
||||
}
|
||||
|
||||
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);
|
||||
};
|
||||
($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, &self.value, factor as u64);
|
||||
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_scale_tests
|
||||
{
|
||||
($name: ident, $lname: ident, $big: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_scale_tests!(body $name, $lname, $big);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident, $big: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_scale_tests!(body $name, $lname, $big);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident, $big: ident) => {
|
||||
let fname = build_test_path("scale", stringify!($name));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (neg0, abytes) = case.get("a").unwrap();
|
||||
let (neg1, bbytes) = case.get("b").unwrap();
|
||||
let (neg2, cbytes) = case.get("c").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2);
|
||||
|
||||
let a = $name::from_bytes(abytes);
|
||||
let b = $name::from_bytes(bbytes);
|
||||
let c = $big::from_bytes(cbytes);
|
||||
assert_eq!(c, &a * b.value[0]);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
pub(crate) fn shiftl(res: &mut [u64], copy: &[u64], amt: usize) {
|
||||
let digits = amt / 64;
|
||||
let bits = amt % 64;
|
||||
|
||||
let mut carry = 0;
|
||||
let shift = 64 - bits;
|
||||
|
||||
for i in 0..res.len() {
|
||||
let base = if i >= digits { copy[i-digits] } else { 0 };
|
||||
let new_carry = if shift == 64 { 0 } else { base >> shift };
|
||||
res[i] = (base << bits) | carry;
|
||||
carry = new_carry;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn shiftr(res: &mut [u64], copy: &[u64], amt: usize) {
|
||||
let digits = amt / 64;
|
||||
let bits = amt % 64;
|
||||
|
||||
let mut carry = 0;
|
||||
let mask = !(0xFFFFFFFFFFFFFFFF << bits);
|
||||
let shift = (64 - bits) as u32;
|
||||
|
||||
for (idx, val) in res.iter_mut().enumerate().rev() {
|
||||
let target = idx + digits;
|
||||
let base = if target >= copy.len() { 0 } else { copy[target] };
|
||||
let (new_carry, _) = (base & mask).overflowing_shl(shift);
|
||||
*val = (base >> bits) | carry;
|
||||
carry = new_carry;
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! shift_impls
|
||||
{
|
||||
($name: ident, $size: expr) => {
|
||||
impl ShlAssign<usize> for $name {
|
||||
fn shl_assign(&mut self, amt: usize) {
|
||||
let copy = self.value.clone();
|
||||
shiftl(&mut self.value, ©, amt);
|
||||
}
|
||||
}
|
||||
|
||||
impl Shl<usize> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn shl(mut self, amt: usize) -> $name {
|
||||
let copy = self.value.clone();
|
||||
shiftl(&mut self.value, ©, amt);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Shl<usize> for &'a $name {
|
||||
type Output = $name;
|
||||
|
||||
fn shl(self, amt: usize) -> $name {
|
||||
let mut res = $name{ value: self.value.clone() };
|
||||
shiftl(&mut res.value, &self.value, amt);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl ShrAssign<usize> for $name {
|
||||
fn shr_assign(&mut self, amt: usize) {
|
||||
let copy = self.value.clone();
|
||||
shiftr(&mut self.value, ©, amt);
|
||||
}
|
||||
}
|
||||
|
||||
impl Shr<usize> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn shr(mut self, amt: usize) -> $name {
|
||||
let copy = self.value.clone();
|
||||
shiftr(&mut self.value, ©, amt);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Shr<usize> for &'a $name {
|
||||
type Output = $name;
|
||||
|
||||
fn shr(self, amt: usize) -> $name {
|
||||
let mut res = $name{ value: self.value.clone() };
|
||||
shiftr(&mut res.value, &self.value, amt);
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_shiftl_tests {
|
||||
($name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_shiftl_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_shiftl_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident) => {
|
||||
let fname = build_test_path("shiftl", stringify!($name));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (neg0, abytes) = case.get("a").unwrap();
|
||||
let (neg1, lbytes) = case.get("l").unwrap();
|
||||
let (neg2, rbytes) = case.get("r").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2);
|
||||
|
||||
let a = $name::from_bytes(abytes);
|
||||
let l = $name::from_bytes(lbytes);
|
||||
let r = $name::from_bytes(rbytes);
|
||||
assert_eq!(r, a << usize::from(l));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_shiftr_tests {
|
||||
($name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_shiftr_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_shiftr_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident) => {
|
||||
let fname = build_test_path("shiftr", stringify!($name));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (neg0, abytes) = case.get("a").unwrap();
|
||||
let (neg1, lbytes) = case.get("l").unwrap();
|
||||
let (neg2, rbytes) = case.get("r").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2);
|
||||
|
||||
let a = $name::from_bytes(abytes);
|
||||
let l = $name::from_bytes(lbytes);
|
||||
let r = $name::from_bytes(rbytes);
|
||||
assert_eq!(r, a >> usize::from(l));
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
pub trait SquareRoot {
|
||||
/// Compute the integer square root of the given value. The integer square
|
||||
/// root is the value Z such that the real root R satisfies Z <= R < Z+1.
|
||||
fn sqrt(&self) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! sqrt_impls
|
||||
{
|
||||
($name: ident) => {
|
||||
impl SquareRoot for $name {
|
||||
fn sqrt(&self) -> Self {
|
||||
let mut num = self.clone();
|
||||
let mut res = $name::zero();
|
||||
let mut bit = $name::from(1u64) << ($name::bit_length() - 2);
|
||||
|
||||
while bit > num {
|
||||
bit >>= 2;
|
||||
}
|
||||
|
||||
while !bit.is_zero() {
|
||||
let mut resbit = res.clone();
|
||||
|
||||
resbit += &bit;
|
||||
if num >= resbit {
|
||||
num -= resbit;
|
||||
res += &bit << 1;
|
||||
}
|
||||
|
||||
res >>= 1;
|
||||
bit >>= 2;
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_sqrt_tests {
|
||||
($name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_sqrt_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_sqrt_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident) => {
|
||||
let fname = build_test_path("sqrt", stringify!($name));
|
||||
run_test(fname.to_string(), 2, |case| {
|
||||
let (neg0, abytes) = case.get("a").unwrap();
|
||||
let (neg1, rbytes) = case.get("r").unwrap();
|
||||
assert!(!neg0 && !neg1);
|
||||
|
||||
let a = $name::from_bytes(abytes);
|
||||
let r = $name::from_bytes(rbytes);
|
||||
assert_eq!(r, a.sqrt());
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/// Squaring of large numbers.
|
||||
pub trait Square<Output> {
|
||||
fn square(&self) -> Output;
|
||||
}
|
||||
|
||||
macro_rules! square_impls {
|
||||
($name: ident, $bigger: ident, $size: expr) => {
|
||||
impl Square<$bigger> for $name {
|
||||
fn square(&self) -> $bigger {
|
||||
let mut w = [0; $size/32];
|
||||
let t = $size / 64;
|
||||
|
||||
for i in 0..t {
|
||||
let x128 = self.value[i] as u128;
|
||||
let mut uvb = (w[2*i] as u128) + (x128 * x128);
|
||||
w[2*i] = uvb & 0xFFFFFFFFFFFFFFFF;
|
||||
let mut c = uvb >> 64;
|
||||
for j in (i+1)..t {
|
||||
let xj128 = self.value[j] as u128;
|
||||
let xi128 = self.value[i] as u128;
|
||||
// this first product is safely 128 bits or less,
|
||||
// because the input arguments are both 64 bits.
|
||||
let xij128 = xj128 * xi128;
|
||||
// this next bit may overflow, but will do so by exactly
|
||||
// one bit.
|
||||
let twoxij128 = xij128 << 1;
|
||||
let carried_shl = (xij128 & (1 << 127)) != 0;
|
||||
// this next bit may *also* overflow, but should also do
|
||||
// so by no more than one bit.
|
||||
let (new,carry1) = twoxij128.overflowing_add(c);
|
||||
// ditto ...
|
||||
let wij = w[i+j];
|
||||
let (uvb2,carry2) = new.overflowing_add(wij as u128);
|
||||
// for the value we're going to save for this digit, we
|
||||
// only care about the low bits, so we can forget about
|
||||
// the carry stuff.
|
||||
w[i+j] = uvb2 & 0xFFFFFFFFFFFFFFFF;
|
||||
// for c, though, we do care about the carries, above.
|
||||
// Fortunately, they were both by only one bit, so we
|
||||
// should be able to just back-fix them.
|
||||
c = uvb2 >> 64;
|
||||
if carried_shl { c += 1 << 64; }
|
||||
if carry1 { c += 1 << 64; }
|
||||
if carry2 { c += 1 << 64; }
|
||||
}
|
||||
w[i+t] = c;
|
||||
}
|
||||
let mut res = $bigger::zero();
|
||||
for i in 0..w.len() { res.value[i] = w[i] as u64; }
|
||||
res
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_square_tests {
|
||||
($name: ident, $lname: ident, $dbl: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_square_tests!(body $name, $lname, $dbl);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident, $dbl: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_square_tests!(body $name, $lname, $dbl);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident, $dbl: ident) => {
|
||||
let fname = build_test_path("square", stringify!($name));
|
||||
run_test(fname.to_string(), 2, |case| {
|
||||
let (neg0, abytes) = case.get("a").unwrap();
|
||||
let (neg1, rbytes) = case.get("r").unwrap();
|
||||
assert!(!neg0 && !neg1);
|
||||
|
||||
let a = $name::from_bytes(abytes);
|
||||
let r = $dbl::from_bytes(rbytes);
|
||||
assert_eq!(r, a.square());
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
use unsigned::add::unsafe_addition;
|
||||
|
||||
pub fn subtract(res: &mut [u64], spare: &mut [u64], other: &mut [u64])
|
||||
{
|
||||
for i in 0..res.len() {
|
||||
other[i] = !other[i];
|
||||
}
|
||||
spare[0] = 1;
|
||||
unsafe_addition(other, &spare, true);
|
||||
unsafe_addition(res, &other, true);
|
||||
}
|
||||
|
||||
macro_rules! subtraction_impls
|
||||
{
|
||||
($name: ident, $size: expr) => {
|
||||
impl SubAssign for $name {
|
||||
fn sub_assign(&mut self, rhs: $name) {
|
||||
let mut temp = [0; $size];
|
||||
subtract(&mut self.value, &mut temp, &mut rhs.value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SubAssign<&'a $name> for $name {
|
||||
fn sub_assign(&mut self, rhs: &$name) {
|
||||
let mut temp = [0; $size];
|
||||
subtract(&mut self.value, &mut temp, &mut rhs.value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn sub(self, rhs: $name) -> $name {
|
||||
let mut res = self.clone();
|
||||
let mut temp = [0; $size];
|
||||
subtract(&mut res.value, &mut temp, &mut rhs.value.clone());
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Sub<$name> for &'a $name {
|
||||
type Output = $name;
|
||||
|
||||
fn sub(self, rhs: $name) -> $name {
|
||||
let mut res = self.clone();
|
||||
let mut temp = [0; $size];
|
||||
subtract(&mut res.value, &mut temp, &mut rhs.value.clone());
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Sub<&'a $name> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn sub(self, rhs: &$name) -> $name {
|
||||
let mut res = self.clone();
|
||||
let mut temp = [0; $size];
|
||||
subtract(&mut res.value, &mut temp, &mut rhs.value.clone());
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> Sub<&'a $name> for &'b $name {
|
||||
type Output = $name;
|
||||
|
||||
fn sub(self, rhs: &$name) -> $name {
|
||||
let mut res = self.clone();
|
||||
let mut temp = [0; $size];
|
||||
subtract(&mut res.value, &mut temp, &mut rhs.value.clone());
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_sub_tests {
|
||||
($name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
fn $lname() {
|
||||
generate_sub_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(ignore $name: ident, $lname: ident) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn $lname() {
|
||||
generate_sub_tests!(body $name, $lname);
|
||||
}
|
||||
};
|
||||
(body $name: ident, $lname: ident) => {
|
||||
let fname = build_test_path("sub", stringify!($name));
|
||||
run_test(fname.to_string(), 3, |case| {
|
||||
let (neg0, abytes) = case.get("a").unwrap();
|
||||
let (neg1, bbytes) = case.get("b").unwrap();
|
||||
let (neg2, cbytes) = case.get("c").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2);
|
||||
|
||||
let mut a = $name::from_bytes(abytes);
|
||||
let b = $name::from_bytes(bbytes);
|
||||
let c = $name::from_bytes(cbytes);
|
||||
assert_eq!(c, &a - &b);
|
||||
a -= b;
|
||||
assert_eq!(c, a);
|
||||
});
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user