diff --git a/src/cryptonum/addition.rs b/src/cryptonum/addition.rs index 1886aba..0b08015 100644 --- a/src/cryptonum/addition.rs +++ b/src/cryptonum/addition.rs @@ -5,6 +5,7 @@ use cryptonum::comparison::bignum_ge; use cryptonum::subtraction::raw_subtraction; use std::ops::{Add,AddAssign}; +#[inline(always)] pub fn raw_addition(x: &mut [u64], y: &[u64]) -> u64 { assert_eq!(x.len(), y.len()); @@ -132,7 +133,7 @@ macro_rules! generate_tests { } #[cfg(test)] - mod slow_modular { + mod modular { use cryptonum::encoding::Decoder; use super::*; use testing::run_test; diff --git a/src/cryptonum/barrett.rs b/src/cryptonum/barrett.rs index 2dec58a..7db9c61 100644 --- a/src/cryptonum/barrett.rs +++ b/src/cryptonum/barrett.rs @@ -1,7 +1,7 @@ use cryptonum::{U192, U256, U384, U512, U576, U1024, U2048, U3072, U4096, U8192, U15360}; -use cryptonum::addition::raw_addition; +use cryptonum::addition::{ModAdd,raw_addition}; use cryptonum::comparison::{bignum_cmp,bignum_ge}; use cryptonum::division::divmod; use cryptonum::multiplication::raw_multiplication; @@ -101,6 +101,27 @@ macro_rules! generate_barrett_implementations { } } } + + impl ModAdd<$bname> for $name { + fn modadd(&mut self, y: &$name, m: &$bname) { + let carry = raw_addition(&mut self.values, &y.values); + let msized = &m.m[0..$size/64]; + if carry > 0 { + let mut left = [0; $size/64 + 1]; + (&mut left[0..$size/64]).copy_from_slice(&self.values); + left[$size/64] = carry; + let mut right = [0; $size/64 + 1]; + (&mut right[0..$size/64]).copy_from_slice(msized); + raw_subtraction(&mut left, &right); + for i in 0..self.values.len() { + self.values[i] = left[i]; + } + } + if bignum_ge(&self.values, msized) { + raw_subtraction(&mut self.values, msized); + } + } + } }; } @@ -202,6 +223,37 @@ macro_rules! generate_tests { } )* } + + #[cfg(test)] + mod modadd { + use cryptonum::encoding::Decoder; + use super::*; + use testing::run_test; + + $( + #[test] + #[allow(non_snake_case)] + fn $name() { + let fname = format!("tests/math/modadd{}.test", + 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, cbytes) = case.get("c").unwrap(); + let (neg3, mbytes) = case.get("m").unwrap(); + + assert!(!neg0 && !neg1 && !neg2 && !neg3); + let mut a = $name::from_bytes(abytes); + let b = $name::from_bytes(bbytes); + let m = $name::from_bytes(mbytes); + let mu = $bname::new(&m); + let c = $name::from_bytes(cbytes); + a.modadd(&b, &mu); + assert_eq!(a, c); + }); + } + )* + } } } diff --git a/src/cryptonum/multiplication.rs b/src/cryptonum/multiplication.rs index bbf272f..840b761 100644 --- a/src/cryptonum/multiplication.rs +++ b/src/cryptonum/multiplication.rs @@ -9,6 +9,7 @@ pub trait ModMul { } // This is algorithm 14.12 from "Handbook of Applied Cryptography" +#[inline(always)] pub fn raw_multiplication(x: &[u64], y: &[u64], w: &mut [u64]) { assert_eq!(x.len(), y.len()); diff --git a/src/cryptonum/squaring.rs b/src/cryptonum/squaring.rs index 6d51b58..aa6305d 100644 --- a/src/cryptonum/squaring.rs +++ b/src/cryptonum/squaring.rs @@ -7,6 +7,7 @@ pub trait ModSquare } // This is algorithm 14.16 from "Handbook of Applied Cryptography". +#[inline(always)] pub fn raw_square(x: &[u64], result: &mut [u64]) { assert_eq!(x.len() * 2, result.len()); diff --git a/src/cryptonum/subtraction.rs b/src/cryptonum/subtraction.rs index 923547d..ae94bd4 100644 --- a/src/cryptonum/subtraction.rs +++ b/src/cryptonum/subtraction.rs @@ -4,6 +4,7 @@ use cryptonum::{U192, U256, U384, U512, U576, use cryptonum::addition::raw_addition; use std::ops::{Sub,SubAssign}; +#[inline(always)] pub fn raw_subtraction(x: &mut [u64], y: &[u64]) { assert_eq!(x.len(), y.len());