}
}
+impl<'a> FiniteNimberRef<'a> {
+ fn sqrt_recurse(self, level: usize) -> FiniteNimber {
+ match level.checked_sub(1) {
+ Some(sublevel) => {
+ let (lo, hi) = self.split(sublevel);
+ let hi_root = hi.sqrt_recurse(sublevel);
+ let sum = hi.mul_by_h(sublevel) + lo;
+ let sum_root = sum.to_ref().sqrt_recurse(sublevel);
+ sum_root.to_ref().join(hi_root.to_ref(), sublevel)
+ }
+
+ // At level 0, both elements of GF(2) square-root to themselves.
+ None => self.into(),
+ }
+ }
+}
+
+impl FiniteNimber {
+ /// Compute the square root of a nimber. Every nimber has a unique
+ /// square root, so this function can't fail, and doesn't need to
+ /// return a list or a tuple or anything more complicated than a
+ /// single nimber.
+ pub fn sqrt(&self) -> FiniteNimber {
+ let r = self.to_ref();
+ r.sqrt_recurse(r.level())
+ }
+}
+
impl_binop_wrappers!(Add, add, AddAssign, add_assign);
impl_binop_wrappers!(Sub, sub, SubAssign, sub_assign);
impl_binop_wrappers!(Mul, mul, MulAssign, mul_assign);
// panic.
let _ = FiniteNimber::from(0x1234) / FiniteNimber::from(0);
}
+
+ #[test]
+ fn sqrt() {
+ assert_eq!(FiniteNimber::from(0xde).sqrt(), FiniteNimber::from(0x80));
+ assert_eq!(
+ FiniteNimber::from(0xde4a).sqrt(),
+ FiniteNimber::from(0x8000)
+ );
+
+ assert_eq!(
+ FiniteNimber::from(vec![
+ 0xd0e74a0945d35342,
+ 0xfa91473032b5438a,
+ 0xe17bdc047300f99d,
+ 0x1a51cba4adb8ddb9,
+ 0xdc06e76f54f372c0,
+ 0xe74d7b7c65542a19,
+ 0xffe69bcb391c628b,
+ 0x32ae6e49dcd65156,
+ ])
+ .sqrt(),
+ FiniteNimber::from(vec![
+ 0x3f84d5b5b5470917,
+ 0xc0ac29b7c97c50dd,
+ 0xbe5466cf34e90c6c,
+ 0x452821e638d01377,
+ 0x082efa98ec4e6c89,
+ 0xa4093822299f31d0,
+ 0x13198a2e03707344,
+ 0x243f6a8885a308d3,
+ ])
+ );
+ }
}