chiark / gitweb /
Multiplication passes first test!
authorSimon Tatham <anakin@pobox.com>
Fri, 11 Apr 2025 17:46:44 +0000 (18:46 +0100)
committerSimon Tatham <anakin@pobox.com>
Fri, 11 Apr 2025 17:46:44 +0000 (18:46 +0100)
src/finitenimber.rs

index f2cac7f861ccaee53ad6e70c906a19cbdd82f7cc..7197401d147a42e1bd4ad12413b0a53803c9d0a0 100644 (file)
@@ -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<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::*;
@@ -451,4 +514,12 @@ mod tests {
             ])
         );
     }
+
+    #[test]
+    fn mul() {
+        assert_eq!(
+            FiniteNimber::from(0xd) * FiniteNimber::from(0xb),
+            FiniteNimber::from(0x5)
+        );
+    }
 }