From cab796ae353a8b2c2da2927ca92eb9b8c43c10ae Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 11 Apr 2025 18:44:21 +0100 Subject: [PATCH] Determine starting level --- src/finitenimber.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/finitenimber.rs b/src/finitenimber.rs index d4dcc33..9cbda22 100644 --- a/src/finitenimber.rs +++ b/src/finitenimber.rs @@ -68,6 +68,35 @@ impl<'a> FiniteNimberRef<'a> { } } + fn level(self) -> usize { + fn word_level(w: Word) -> usize { + let log_w: u32 = + (Word::BITS - 1).saturating_sub(w.leading_zeros()); + u32::BITS.saturating_sub(log_w.leading_zeros()) as usize + } + + fn usize_level(w: usize) -> usize { + let log_w: u32 = (usize::BITS - 1) - w.leading_zeros(); + u32::BITS.saturating_sub(log_w.leading_zeros()) as usize + } + + match self { + OneWord(v) => word_level(v), + Slice(s) => { + match s + .iter() + .enumerate() + .rev() + .find(|(_index, word)| **word != 0) + { + None => 0, + Some((0, w)) => word_level(*w), + Some((i, _)) => usize_level(i) + (WORDLEVELS + 1), + } + } + } + } + fn split( self, level: usize, @@ -352,6 +381,30 @@ mod tests { ); } + #[test] + fn levels() { + assert_eq!(FiniteNimber(vec![]).to_ref().level(), 0); + assert_eq!(FiniteNimber(vec![0]).to_ref().level(), 0); + assert_eq!(FiniteNimber(vec![1]).to_ref().level(), 0); + assert_eq!(FiniteNimber(vec![2]).to_ref().level(), 1); + assert_eq!(FiniteNimber(vec![3]).to_ref().level(), 1); + assert_eq!(FiniteNimber(vec![4]).to_ref().level(), 2); + assert_eq!(FiniteNimber(vec![0xf]).to_ref().level(), 2); + assert_eq!(FiniteNimber(vec![0x10]).to_ref().level(), 3); + assert_eq!(FiniteNimber(vec![0xff]).to_ref().level(), 3); + assert_eq!(FiniteNimber(vec![0x0100]).to_ref().level(), 4); + assert_eq!(FiniteNimber(vec![0xffff]).to_ref().level(), 4); + assert_eq!(FiniteNimber(vec![0x00010000]).to_ref().level(), 5); + assert_eq!(FiniteNimber(vec![0xffffffff]).to_ref().level(), 5); + assert_eq!(FiniteNimber(vec![0x0000000100000000]).to_ref().level(), 6); + assert_eq!(FiniteNimber(vec![0xffffffffffffffff]).to_ref().level(), 6); + + assert_eq!(FiniteNimber(vec![0x55, 0, 0, 0]).to_ref().level(), 3); + assert_eq!(FiniteNimber(vec![0x55, 1, 0, 0]).to_ref().level(), 7); + assert_eq!(FiniteNimber(vec![0x55, 1, 1, 0]).to_ref().level(), 8); + assert_eq!(FiniteNimber(vec![0x55, 1, 1, 1]).to_ref().level(), 8); + } + #[test] fn addition() { let a = FiniteNimber::from(0b1100); -- 2.30.2