chiark / gitweb /
I think that's refs, split and join?
authorSimon Tatham <anakin@pobox.com>
Fri, 11 Apr 2025 07:58:46 +0000 (08:58 +0100)
committerSimon Tatham <anakin@pobox.com>
Fri, 11 Apr 2025 07:58:46 +0000 (08:58 +0100)
src/finitenimber.rs

index 51cfc68bbba7ec37b5e47019141d95dff321e24a..8577a23fd516432a5ae32f0b94aaf07b5690f5c9 100644 (file)
@@ -1,4 +1,4 @@
-use std::ops::Add;
+use core::ops::Add;
 
 type Word = u64; // element type of the vectors we use
 const WORDLEVELS: usize = 6; // 2^{2^6} = 64 = size of Word
@@ -73,7 +73,7 @@ impl<'a> FiniteNimberRef<'a> {
         'b: 'c,
     {
         match self {
-            OneWord(v) => std::slice::from_ref(v),
+            OneWord(v) => core::slice::from_ref(v),
             Slice(s) => s,
         }
     }
@@ -114,4 +114,48 @@ impl<'a> FiniteNimberRef<'a> {
             },
         }
     }
+
+    fn join(self, hi: FiniteNimberRef<'_>, level: usize) -> FiniteNimber {
+        match level.checked_sub(WORDLEVELS) {
+            None => {
+                // If level < WORDLEVELS then we can cast to Word any old way
+                let bits = 1 << (level as Word);
+                let mask = bits - 1;
+                let vlo = self.low_word();
+                let vhi = hi.low_word();
+                ((vlo & mask) | ((vhi & mask) << bits)).into()
+            }
+            Some(wordlevel) => {
+                match wordlevel
+                    .try_into()
+                    .ok()
+                    .and_then(|w| 1usize.checked_shl(w))
+                {
+                    Some(words) => {
+                        let slo = self.as_slice();
+                        let shi = hi.as_slice();
+                        let padding = words.saturating_sub(slo.len());
+                        FiniteNimber(
+                            slo.iter()
+                                .cloned()
+                                .take(words)
+                                .chain(core::iter::repeat(0).take(padding))
+                                .chain(shi.iter().cloned().take(words))
+                                .collect(),
+                        )
+                    }
+                    None => FiniteNimber(self.as_slice().into()),
+                }
+            }
+        }
+    }
+}
+
+impl<'a> From<&'a FiniteNimber> for FiniteNimberRef<'a> {
+    fn from(n: &'a FiniteNimber) -> Self {
+        match n.0.len() {
+            0 => Self::zero(),
+            _ => Slice(&n.0),
+        }
+    }
 }