/// A type representing a finite nimber.
#[derive(Clone, PartialEq, Eq, Hash)]
-pub struct FiniteNimber(Vec<Word>);
+pub struct FiniteNimber(FiniteNimberEnum);
+
+/// A type representing a finite nimber.
+#[derive(Clone, PartialEq, Eq, Hash)]
+enum FiniteNimberEnum {
+ Single(Word),
+ Vector(Vec<Word>),
+}
#[derive(Clone, Copy)]
pub enum FiniteNimberRef<'a> {
- OneWord(Word),
+ Single(Word),
Slice(&'a [Word]),
}
-use FiniteNimberRef::*;
impl Debug for FiniteNimber {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
- write!(f, "FiniteNimber[")?;
- let mut sep: &str = "";
- for v in &self.0 {
- write!(f, "{}0x{:016x}", sep, v)?;
- sep = ", ";
+ match &self.0 {
+ FiniteNimberEnum::Single(v) => {
+ write!(f, "FiniteNimberEnum::Single(0x{:16x})", v)
+ }
+ FiniteNimberEnum::Vector(s) => {
+ write!(f, "FiniteNimberEnum::Vector[")?;
+ let mut sep: &str = "";
+ for v in s {
+ write!(f, "{}0x{:016x}", sep, v)?;
+ sep = ", ";
+ }
+ write!(f, "]")
+ }
}
- write!(f, "]")
}
}
impl Debug for FiniteNimberRef<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
match self {
- OneWord(v) => write!(f, "FiniteNimberRef::OneWord(0x{:16x})", v),
- Slice(s) => {
+ FiniteNimberRef::Single(v) => {
+ write!(f, "FiniteNimberRef::Single(0x{:16x})", v)
+ }
+ FiniteNimberRef::Slice(s) => {
write!(f, "FiniteNimberRef::Slice[")?;
let mut sep: &str = "";
for v in *s {
impl Display for FiniteNimber {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
- if !f.alternate()
- && self.to_ref().level() < WORDLEVELS
- && self.0[0] < 10
- {
- write!(f, "*{}", self.0[0])
+ let r = self.to_ref();
+ if !f.alternate() && r.level() < WORDLEVELS && r.low_word() < 10 {
+ write!(f, "*{}", r.low_word())
} else {
write!(f, "*0x")?;
let mut started = false;
- for v in self.0.iter().rev() {
+ for v in r.as_slice().iter().rev() {
if started {
write!(f, "{:016x}", v)?;
} else if *v != 0 {
impl Borrow<[Word]> for FiniteNimber {
fn borrow(&self) -> &[Word] {
- &self.0
+ self.as_slice()
}
}
impl<'a> FiniteNimberRef<'a> {
fn zero() -> Self {
- OneWord(0)
+ FiniteNimberRef::Single(0)
}
fn low_word(self) -> Word {
match self {
- OneWord(v) => v,
- Slice(s) => {
+ FiniteNimberRef::Single(v) => v,
+ FiniteNimberRef::Slice(s) => {
*(s.first().expect("FiniteNimberRef::Slice is never empty"))
}
}
'b: 'c,
{
match self {
- OneWord(v) => core::slice::from_ref(v),
- Slice(s) => s,
+ FiniteNimberRef::Single(v) => core::slice::from_ref(v),
+ FiniteNimberRef::Slice(s) => s,
}
}
}
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),
+ FiniteNimberRef::Single(v) => word_level(v),
+ FiniteNimberRef::Slice(s) => {
+ let w = s.len().checked_sub(1).expect("slice representation must always be non-empty");
+ match w {
+ 0 => word_level(s[0]),
+ w => usize_level(w) + (WORDLEVELS + 1),
}
}
}
let bits = 1 << (level as Word);
let mask = (1 << bits) - 1;
let v = self.low_word();
- return (OneWord(v & mask), OneWord((v >> bits) & mask));
+ return (
+ FiniteNimberRef::Single(v & mask),
+ FiniteNimberRef::Single((v >> bits) & mask),
+ );
}
Some(wordlevel) => match self {
- OneWord(v) => (OneWord(v), Self::zero()),
- Slice(s) => {
+ FiniteNimberRef::Single(v) => {
+ (FiniteNimberRef::Single(v), Self::zero())
+ }
+ FiniteNimberRef::Slice(s) => {
match wordlevel
.try_into()
.ok()
"FiniteNimberRef::Slice is never empty",
);
match iter.next() {
- Some(hi) => (Slice(lo), Slice(hi)),
- None => (Slice(lo), Self::zero()),
+ Some(hi) => (
+ FiniteNimberRef::Slice(lo),
+ FiniteNimberRef::Slice(hi),
+ ),
+ None => {
+ (FiniteNimberRef::Slice(lo), Self::zero())
+ }
}
}
None => (self.clone(), Self::zero()),
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(),
- )
+ let vec: Vec<_> = slo
+ .iter()
+ .cloned()
+ .take(words)
+ .chain(core::iter::repeat(0).take(padding))
+ .chain(shi.iter().cloned().take(words))
+ .collect();
+ FiniteNimber::from(vec)
}
- None => FiniteNimber(self.as_slice().into()),
+ None => FiniteNimber::from(self.as_slice()),
}
}
}
impl FiniteNimber {
fn to_ref(&self) -> FiniteNimberRef {
- match self.0.len() {
- 0 => FiniteNimberRef::zero(),
- _ => Slice(&self.0),
+ match &self.0 {
+ FiniteNimberEnum::Single(w) => FiniteNimberRef::Single(*w),
+ FiniteNimberEnum::Vector(v) => match v.len() {
+ 0 => FiniteNimberRef::zero(),
+ _ => FiniteNimberRef::Slice(&v),
+ },
+ }
+ }
+
+ fn as_slice(&self) -> &[Word] {
+ match &self.0 {
+ FiniteNimberEnum::Single(w) => core::slice::from_ref(w),
+ FiniteNimberEnum::Vector(v) => &v,
}
}
}
impl From<FiniteNimberRef<'_>> for FiniteNimber {
fn from(n: FiniteNimberRef) -> Self {
- FiniteNimber(n.as_slice().into())
+ match n {
+ FiniteNimberRef::Single(w) => Self(FiniteNimberEnum::Single(w)),
+ FiniteNimberRef::Slice(v) => FiniteNimber::from(v),
+ }
}
}
impl From<Word> for FiniteNimber {
fn from(val: Word) -> FiniteNimber {
- FiniteNimber(vec![val])
+ Self(FiniteNimberEnum::Single(val))
}
}
impl From<Vec<Word>> for FiniteNimber {
- fn from(val: Vec<Word>) -> FiniteNimber {
- FiniteNimber(val)
+ fn from(mut vec: Vec<Word>) -> FiniteNimber {
+ match vec
+ .iter()
+ .enumerate()
+ .rev()
+ .find(|(_index, word)| **word != 0)
+ {
+ None => Self(FiniteNimberEnum::Single(0)),
+ Some((0, w)) => Self(FiniteNimberEnum::Single(*w)),
+ Some((pos, _)) => {
+ vec.truncate(pos + 1);
+ Self(FiniteNimberEnum::Vector(vec))
+ }
+ }
}
}
impl From<&[Word]> for FiniteNimber {
- fn from(val: &[Word]) -> FiniteNimber {
- FiniteNimber(val.into())
+ fn from(slice: &[Word]) -> FiniteNimber {
+ match slice
+ .iter()
+ .enumerate()
+ .rev()
+ .find(|(_index, word)| **word != 0)
+ {
+ None => Self(FiniteNimberEnum::Single(0)),
+ Some((0, w)) => Self(FiniteNimberEnum::Single(*w)),
+ Some(_) => Self(FiniteNimberEnum::Vector(slice.into()))
+ }
}
}
impl<'a, 'b> Add<FiniteNimberRef<'a>> for FiniteNimberRef<'b> {
type Output = FiniteNimber;
fn add(self, other: FiniteNimberRef<'a>) -> FiniteNimber {
- FiniteNimber(
- self.as_slice()
- .iter()
- .cloned()
- .zip_longest(other.as_slice().iter().cloned())
- .map(|pair| pair.reduce(|a, b| a ^ b))
- .collect(),
- )
+ let vec: Vec<_> = self.as_slice()
+ .iter()
+ .cloned()
+ .zip_longest(other.as_slice().iter().cloned())
+ .map(|pair| pair.reduce(|a, b| a ^ b))
+ .collect();
+ FiniteNimber::from(vec)
}
}