use core::{cmp::Ordering, ops::Bound};
use num_bigint::BigUint;
use super::{Domain, Iterable};
impl Domain for BigUint {
const DISCRETE: bool = true;
#[allow(clippy::arithmetic_side_effects)]
fn predecessor(&self) -> Option<Self> {
match Self::minimum() {
Bound::Unbounded | Bound::Excluded(_) => unreachable!(),
Bound::Included(min) => {
if self == &min {
None
} else {
Some(self - Self::from(1_usize))
}
}
}
}
#[allow(clippy::arithmetic_side_effects)]
fn successor(&self) -> Option<Self> {
Some(self + Self::from(1_usize))
}
fn minimum() -> Bound<Self> {
Bound::Included(Self::from(0_usize))
}
#[allow(clippy::arithmetic_side_effects)]
#[must_use]
fn shares_neighbour_with(&self, other: &Self) -> bool {
let other_val = other;
let (big, small) = match self.cmp(other_val) {
Ordering::Less => (other_val, self),
Ordering::Equal => return false,
Ordering::Greater => (self, other_val),
};
big - small == Self::from(2_usize)
}
}
impl Iterable for BigUint {
type Output = Self;
fn next(&self) -> Option<Self::Output> {
self.successor()
}
}
#[cfg(test)]
mod tests {
use num_bigint::BigUint;
use crate::Domain;
#[test]
fn is_next_to() {
assert!(BigUint::from(2_u8).is_next_to(&BigUint::from(3_u8)));
assert!(!BigUint::from(2_u8).is_next_to(&BigUint::from(4_u8)));
}
#[test]
fn shares_neighbour_with() {
assert!(!BigUint::from(2_u8).shares_neighbour_with(&BigUint::from(2_u8)));
assert!(!BigUint::from(42_u8).shares_neighbour_with(&BigUint::from(45_u8)));
assert!(!BigUint::from(45_u8).shares_neighbour_with(&BigUint::from(42_u8)));
assert!(BigUint::from(42_u8).shares_neighbour_with(&BigUint::from(44_u8)));
assert!(BigUint::from(44_u8).shares_neighbour_with(&BigUint::from(42_u8)));
}
#[test]
fn predecessor() {
assert_eq!(BigUint::from(42_u8).predecessor(), Some(BigUint::from(41_u8)));
assert_eq!(BigUint::from(0_u8).predecessor(), None);
}
#[test]
fn successor() {
assert_eq!(BigUint::from(42_u8).successor(), Some(BigUint::from(43_u8)));
}
}