From: Simon Tatham Date: Fri, 11 Apr 2025 17:46:44 +0000 (+0100) Subject: Multiplication passes first test! X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=1dcfa660ef10571a0d01061f96b22abffd76a6ce;p=nimber.git Multiplication passes first test! --- diff --git a/src/finitenimber.rs b/src/finitenimber.rs index f2cac7f..7197401 100644 --- a/src/finitenimber.rs +++ b/src/finitenimber.rs @@ -1,5 +1,6 @@ +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 @@ -267,6 +268,68 @@ impl<'a> FiniteNimberRef<'a> { } } +impl<'a, 'b> Mul> 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 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 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::*; @@ -451,4 +514,12 @@ mod tests { ]) ); } + + #[test] + fn mul() { + assert_eq!( + FiniteNimber::from(0xd) * FiniteNimber::from(0xb), + FiniteNimber::from(0x5) + ); + } }