}
}
+ 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,
);
}
+ #[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);