diff --git a/src/unsigned/barrett.rs b/src/unsigned/barrett.rs index 2044c45..cb43dc9 100644 --- a/src/unsigned/barrett.rs +++ b/src/unsigned/barrett.rs @@ -1,78 +1,98 @@ macro_rules! barrett_impl { ($bar: ident, $name: ident, $name64: ident, $dbl: ident, $dbl64: ident) => { - pub struct $bar { - pub(crate) k: usize, - pub(crate) m: $name64, - pub(crate) mu: $name64 - } + #[derive(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 } - } + 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 } + } - // Reduce the input by this value; in other words, perform a mod - // operation. - 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) - } - } + /// 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 } + } - impl $name { - /// Generate a Barrett number from this number. - pub fn generate_barrett(&self) -> $bar { - $bar::new(self.clone()) - } + // 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) + } + } - #[cfg(test)] - pub(crate) fn new_barrett(k: usize, m: $name64, mu: $name64) -> $bar { - $bar{ k: k, m: m, mu: mu } - } - } + 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() + } + } }; }