From: Simon Tatham Date: Sat, 12 Apr 2025 12:08:19 +0000 (+0100) Subject: Square roots. X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=dcebde96e1db9a21f3f57113be9e430daf5f4ffa;p=nimber.git Square roots. --- diff --git a/src/finitenimber.rs b/src/finitenimber.rs index 6fe1242..c87fe1b 100644 --- a/src/finitenimber.rs +++ b/src/finitenimber.rs @@ -449,6 +449,34 @@ impl<'a, 'b> Div> for FiniteNimberRef<'b> { } } +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); @@ -809,4 +837,37 @@ mod tests { // 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, + ]) + ); + } }