+use core::cmp::max;
use core::fmt::{Debug, Formatter};
-use core::ops::Add;
+use core::ops::{Add, Mul};
type Word = u64; // element type of the vectors we use
const WORDLEVELS: usize = 6; // 2^{2^6} = 64 = size of Word
}
}
+impl<'a, 'b> Mul<FiniteNimberRef<'a>> for FiniteNimberRef<'b> {
+ type Output = FiniteNimber;
+ fn mul(self, other: FiniteNimberRef<'a>) -> FiniteNimber {
+ let level = max(self.level(), other.level());
+ match level.checked_sub(1) {
+ Some(sublevel) => {
+ let (alo, ahi) = self.split(sublevel);
+ let (blo, bhi) = other.split(sublevel);
+ let karatsuba = (alo + ahi) * (blo + bhi);
+ let albl = alo * blo;
+ let ahbh = ahi * bhi;
+ (albl.to_ref() + ahbh.to_ref().mul_by_h(sublevel).to_ref())
+ .to_ref()
+ .join(
+ (karatsuba.to_ref() + albl.to_ref()).to_ref(),
+ sublevel,
+ )
+ }
+
+ // At level 0, we're in GF(2), so multiplication looks
+ // like bitwise AND.
+ None => FiniteNimber::from(self.low_word() & other.low_word()),
+ }
+ }
+}
+
+impl Mul<&FiniteNimber> for &FiniteNimber {
+ type Output = FiniteNimber;
+ fn mul(self, other: &FiniteNimber) -> FiniteNimber {
+ let aref: FiniteNimberRef = self.into();
+ let bref: FiniteNimberRef = other.into();
+ aref * bref
+ }
+}
+
+impl Mul<&FiniteNimber> for FiniteNimber {
+ type Output = FiniteNimber;
+ fn mul(self, other: &FiniteNimber) -> FiniteNimber {
+ let aref: FiniteNimberRef = (&self).into();
+ let bref: FiniteNimberRef = other.into();
+ aref * bref
+ }
+}
+
+impl Mul<FiniteNimber> for &FiniteNimber {
+ type Output = FiniteNimber;
+ fn mul(self, other: FiniteNimber) -> FiniteNimber {
+ let aref: FiniteNimberRef = self.into();
+ let bref: FiniteNimberRef = (&other).into();
+ aref * bref
+ }
+}
+
+impl Mul<FiniteNimber> for FiniteNimber {
+ type Output = FiniteNimber;
+ fn mul(self, other: FiniteNimber) -> FiniteNimber {
+ let aref: FiniteNimberRef = (&self).into();
+ let bref: FiniteNimberRef = (&other).into();
+ aref * bref
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
])
);
}
+
+ #[test]
+ fn mul() {
+ assert_eq!(
+ FiniteNimber::from(0xd) * FiniteNimber::from(0xb),
+ FiniteNimber::from(0x5)
+ );
+ }
}