use std::fmt::Display;
pub const MAX_BITSET_DOMAIN_SIZE: usize = 128;
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq)]
pub struct BitSetDomainState {
pub mask: u128,
pub size: usize,
}
#[doc(hidden)]
#[derive(Debug, Clone)]
pub struct BitSetDomain {
mask: u128,
min_val: i32,
max_val: i32,
universe_size: usize,
}
impl Display for BitSetDomain {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut s = String::new();
use std::fmt::Write;
write!(s, "[").expect("writing to String should never fail");
if self.is_empty() {
write!(s, "|").expect("writing to String should never fail");
} else {
let mut first = true;
let mut in_domain = true;
for i in 0..self.universe_size {
let value = self.min_val + i as i32;
let bit_set = (self.mask & (1u128 << i)) != 0;
if bit_set && in_domain {
if !first {
write!(s, ",").expect("writing to String should never fail");
}
write!(s, "{}", value).expect("writing to String should never fail");
first = false;
}
if !bit_set && in_domain && !first {
write!(s, "|").expect("writing to String should never fail");
in_domain = false;
first = true;
}
if bit_set && !in_domain {
if !first {
write!(s, ",").expect("writing to String should never fail");
}
write!(s, "{}", value).expect("writing to String should never fail");
first = false;
}
}
if in_domain {
write!(s, "|").expect("writing to String should never fail");
}
}
write!(s, "]").expect("writing to String should never fail");
write!(f, "{}", s)
}
}
impl BitSetDomain {
pub fn new_invalid() -> Self {
BitSetDomain {
mask: 0,
min_val: 1, max_val: 0, universe_size: 0,
}
}
pub fn is_invalid(&self) -> bool {
self.max_val < self.min_val
}
pub fn new(min_val: i32, max_val: i32) -> Self {
if min_val > max_val {
return Self::new(max_val, min_val);
}
let universe_size = (max_val - min_val + 1) as usize;
if universe_size > MAX_BITSET_DOMAIN_SIZE {
return Self::new_invalid();
}
let mask = if universe_size == 128 {
u128::MAX
} else {
(1u128 << universe_size) - 1
};
BitSetDomain {
mask,
min_val,
max_val,
universe_size,
}
}
pub fn try_new(min_val: i32, max_val: i32) -> Result<Self, String> {
if min_val > max_val {
return Self::try_new(max_val, min_val);
}
let universe_size = (max_val - min_val + 1) as usize;
if universe_size > MAX_BITSET_DOMAIN_SIZE {
return Err(format!("BitSetDomain supports at most {} values, got {} values in range [{}, {}]",
MAX_BITSET_DOMAIN_SIZE, universe_size, min_val, max_val));
}
let mask = if universe_size == 128 {
u128::MAX
} else {
(1u128 << universe_size) - 1
};
Ok(BitSetDomain {
mask,
min_val,
max_val,
universe_size,
})
}
pub fn new_from_values(values: Vec<i32>) -> Self {
if values.is_empty() {
return BitSetDomain {
mask: 0,
min_val: 0,
max_val: -1, universe_size: 0,
};
}
let min_val = *values.iter().min().unwrap();
let max_val = *values.iter().max().unwrap();
let mut domain = Self::new(min_val, max_val);
if domain.is_invalid() {
return domain; }
domain.mask = 0;
for &value in &values {
domain.insert(value);
}
domain
}
pub fn try_new_from_values(values: Vec<i32>) -> Result<Self, String> {
if values.is_empty() {
return Ok(BitSetDomain {
mask: 0,
min_val: 0,
max_val: -1, universe_size: 0,
});
}
let min_val = *values.iter().min().ok_or("Empty values vector")?;
let max_val = *values.iter().max().ok_or("Empty values vector")?;
let mut domain = Self::try_new(min_val, max_val)?;
domain.mask = 0;
for &value in &values {
domain.insert(value);
}
Ok(domain)
}
pub fn new_empty(min_val: i32, max_val: i32) -> Self {
let mut domain = Self::new(min_val, max_val);
if domain.is_invalid() {
return domain; }
domain.mask = 0;
domain
}
pub fn try_new_empty(min_val: i32, max_val: i32) -> Result<Self, String> {
let mut domain = Self::try_new(min_val, max_val)?;
domain.mask = 0;
Ok(domain)
}
#[inline]
pub fn insert(&mut self, value: i32) -> bool {
if value < self.min_val || value > self.max_val {
return false; }
let bit_pos = (value - self.min_val) as usize;
let was_present = (self.mask & (1u128 << bit_pos)) != 0;
self.mask |= 1u128 << bit_pos;
!was_present
}
#[inline]
pub fn remove(&mut self, value: i32) -> bool {
if value < self.min_val || value > self.max_val {
return false; }
let bit_pos = (value - self.min_val) as usize;
let was_present = (self.mask & (1u128 << bit_pos)) != 0;
self.mask &= !(1u128 << bit_pos);
was_present
}
#[inline]
pub fn contains(&self, value: i32) -> bool {
if value < self.min_val || value > self.max_val {
return false;
}
let bit_pos = (value - self.min_val) as usize;
(self.mask & (1u128 << bit_pos)) != 0
}
#[inline]
pub fn size(&self) -> usize {
self.mask.count_ones() as usize
}
#[inline]
pub fn is_empty(&self) -> bool {
self.mask == 0
}
#[inline]
pub fn is_fixed(&self) -> bool {
self.mask != 0 && (self.mask & (self.mask - 1)) == 0
}
pub fn fixed_value(&self) -> Option<i32> {
if self.is_fixed() {
let bit_pos = self.mask.trailing_zeros() as usize;
Some(self.min_val + bit_pos as i32)
} else {
None
}
}
#[inline]
pub fn min(&self) -> Option<i32> {
if self.mask == 0 {
return None;
}
let first_bit = self.mask.trailing_zeros() as usize;
Some(self.min_val + first_bit as i32)
}
#[inline]
pub fn max(&self) -> Option<i32> {
if self.mask == 0 {
return None;
}
let last_bit = (127 - self.mask.leading_zeros()) as usize;
Some(self.min_val + last_bit as i32)
}
pub fn remove_all(&mut self) {
self.mask = 0;
}
pub fn remove_all_but(&mut self, value: i32) {
if !self.contains(value) {
self.remove_all();
return;
}
let bit_pos = (value - self.min_val) as usize;
self.mask = 1u128 << bit_pos;
}
pub fn remove_below(&mut self, threshold: i32) {
if threshold <= self.min_val {
return; }
let remove_bits = if threshold > self.max_val {
u128::MAX } else {
let remove_count = (threshold - self.min_val) as usize;
if remove_count >= 128 {
u128::MAX
} else {
(1u128 << remove_count) - 1
}
};
self.mask &= !remove_bits;
}
pub fn remove_above(&mut self, threshold: i32) {
if threshold >= self.max_val {
return; }
if threshold < self.min_val {
self.remove_all();
return;
}
let keep_count = (threshold - self.min_val + 1) as usize;
let keep_bits = if keep_count >= 128 {
u128::MAX
} else {
(1u128 << keep_count) - 1
};
self.mask &= keep_bits;
}
pub fn iter(&self) -> BitSetDomainIterator {
BitSetDomainIterator {
mask: self.mask,
min_val: self.min_val,
}
}
pub fn to_vec(&self) -> Vec<i32> {
self.iter().collect()
}
pub fn first(&self) -> Option<i32> {
self.min()
}
pub fn last(&self) -> Option<i32> {
self.max()
}
pub fn universe_size(&self) -> usize {
self.universe_size
}
pub fn min_universe_value(&self) -> i32 {
self.min_val
}
pub fn max_universe_value(&self) -> i32 {
self.max_val
}
pub fn intersect_with(&mut self, other: &BitSetDomain) -> Result<(), String> {
if self.min_val != other.min_val || self.max_val != other.max_val {
return Err("Cannot intersect domains with different universes".to_string());
}
self.mask &= other.mask;
Ok(())
}
pub fn union_with(&mut self, other: &BitSetDomain) -> Result<(), String> {
if self.min_val != other.min_val || self.max_val != other.max_val {
return Err("Cannot union domains with different universes".to_string());
}
self.mask |= other.mask;
Ok(())
}
pub fn is_subset_of(&self, other: &BitSetDomain) -> bool {
if self.min_val != other.min_val || self.max_val != other.max_val {
return false;
}
(self.mask & other.mask) == self.mask
}
pub fn equals(&self, other: &BitSetDomain) -> bool {
self.min_val == other.min_val
&& self.max_val == other.max_val
&& self.mask == other.mask
}
pub fn union_mask(&self, other: &BitSetDomain) -> Option<u128> {
if self.min_val != other.min_val || self.max_val != other.max_val {
return None;
}
Some(self.mask | other.mask)
}
pub fn remove_by_mask(&mut self, remove_mask: u128) -> bool {
let old_mask = self.mask;
self.mask &= !remove_mask;
self.mask != old_mask
}
#[doc(hidden)]
pub fn get_mask(&self) -> u128 {
self.mask
}
#[doc(hidden)]
pub fn get_min_val(&self) -> i32 {
self.min_val
}
#[doc(hidden)]
pub fn save_state(&self) -> BitSetDomainState {
BitSetDomainState {
mask: self.mask,
size: self.size(),
}
}
#[doc(hidden)]
pub fn restore_state(&mut self, state: &BitSetDomainState) {
self.mask = state.mask;
}
pub fn current_mask(&self) -> u128 {
self.mask
}
pub fn restore_mask(&mut self, mask: u128) {
self.mask = mask;
}
}
impl PartialEq for BitSetDomain {
fn eq(&self, other: &Self) -> bool {
self.equals(other)
}
}
impl Eq for BitSetDomain {}
pub struct BitSetDomainIterator {
mask: u128,
min_val: i32,
}
impl Iterator for BitSetDomainIterator {
type Item = i32;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.mask == 0 {
return None;
}
let offset = self.mask.trailing_zeros() as i32;
let value = self.min_val + offset;
self.mask &= self.mask - 1;
Some(value)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let count = self.mask.count_ones() as usize;
(count, Some(count))
}
}
impl IntoIterator for BitSetDomain {
type Item = i32;
type IntoIter = std::vec::IntoIter<i32>;
fn into_iter(self) -> Self::IntoIter {
self.to_vec().into_iter()
}
}
impl<'a> IntoIterator for &'a BitSetDomain {
type Item = i32;
type IntoIter = BitSetDomainIterator;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_basic() {
let domain = BitSetDomain::new(1, 5);
assert_eq!(domain.size(), 5);
assert_eq!(domain.min(), Some(1));
assert_eq!(domain.max(), Some(5));
assert!(!domain.is_empty());
assert!(!domain.is_fixed());
for i in 1..=5 {
assert!(domain.contains(i));
}
assert!(!domain.contains(0));
assert!(!domain.contains(6));
}
#[test]
fn test_new_empty() {
let domain = BitSetDomain::new_empty(1, 5);
assert!(domain.is_empty());
assert_eq!(domain.size(), 0);
assert_eq!(domain.min(), None);
assert_eq!(domain.max(), None);
for i in 1..=5 {
assert!(!domain.contains(i));
}
}
#[test]
fn test_new_from_values() {
let domain = BitSetDomain::new_from_values(vec![2, 4, 6]);
assert_eq!(domain.size(), 3);
assert_eq!(domain.min(), Some(2));
assert_eq!(domain.max(), Some(6));
assert!(domain.contains(2));
assert!(!domain.contains(3));
assert!(domain.contains(4));
assert!(!domain.contains(5));
assert!(domain.contains(6));
let values: Vec<i32> = domain.iter().collect();
assert_eq!(values, vec![2, 4, 6]);
}
#[test]
fn test_new_from_values_empty() {
let domain = BitSetDomain::new_from_values(vec![]);
assert!(domain.is_empty());
assert_eq!(domain.size(), 0);
}
#[test]
fn test_insert_remove() {
let mut domain = BitSetDomain::new_empty(1, 5);
assert!(domain.insert(3));
assert!(domain.insert(1));
assert!(domain.insert(5));
assert!(!domain.insert(3));
assert_eq!(domain.size(), 3);
assert!(domain.contains(1));
assert!(domain.contains(3));
assert!(domain.contains(5));
assert!(domain.remove(3));
assert!(!domain.remove(3)); assert!(domain.remove(1));
assert_eq!(domain.size(), 1);
assert!(!domain.contains(1));
assert!(!domain.contains(3));
assert!(domain.contains(5));
assert!(domain.is_fixed());
assert_eq!(domain.fixed_value(), Some(5));
}
#[test]
fn test_remove_all() {
let mut domain = BitSetDomain::new(1, 5);
assert!(!domain.is_empty());
domain.remove_all();
assert!(domain.is_empty());
assert_eq!(domain.size(), 0);
for i in 1..=5 {
assert!(!domain.contains(i));
}
}
#[test]
fn test_remove_all_but() {
let mut domain = BitSetDomain::new(1, 5);
domain.remove_all_but(3);
assert!(domain.is_fixed());
assert_eq!(domain.fixed_value(), Some(3));
assert_eq!(domain.size(), 1);
assert!(!domain.contains(1));
assert!(!domain.contains(2));
assert!(domain.contains(3));
assert!(!domain.contains(4));
assert!(!domain.contains(5));
}
#[test]
fn test_remove_all_but_missing() {
let mut domain = BitSetDomain::new(1, 5);
domain.remove(3);
domain.remove_all_but(3); assert!(domain.is_empty());
}
#[test]
fn test_remove_below() {
let mut domain = BitSetDomain::new(1, 10);
domain.remove_below(5);
assert_eq!(domain.size(), 6); assert_eq!(domain.min(), Some(5));
assert_eq!(domain.max(), Some(10));
for i in 1..5 {
assert!(!domain.contains(i));
}
for i in 5..=10 {
assert!(domain.contains(i));
}
}
#[test]
fn test_remove_above() {
let mut domain = BitSetDomain::new(1, 10);
domain.remove_above(5);
assert_eq!(domain.size(), 5); assert_eq!(domain.min(), Some(1));
assert_eq!(domain.max(), Some(5));
for i in 1..=5 {
assert!(domain.contains(i));
}
for i in 6..=10 {
assert!(!domain.contains(i));
}
}
#[test]
fn test_intersect_with() {
let mut domain1 = BitSetDomain::new(1, 5);
let mut domain2 = BitSetDomain::new(1, 5);
domain1.remove(1);
domain1.remove(5);
domain2.remove(2);
domain2.remove(4);
domain1.intersect_with(&domain2).unwrap();
assert_eq!(domain1.size(), 1);
assert!(domain1.contains(3));
assert!(!domain1.contains(1));
assert!(!domain1.contains(2));
assert!(!domain1.contains(4));
assert!(!domain1.contains(5));
}
#[test]
fn test_union_with() {
let mut domain1 = BitSetDomain::new(1, 5);
let mut domain2 = BitSetDomain::new(1, 5);
domain1.remove(3);
domain1.remove(4);
domain1.remove(5);
domain2.remove(1);
domain2.remove(2);
domain2.remove(3);
domain1.union_with(&domain2).unwrap();
assert_eq!(domain1.size(), 4);
assert!(domain1.contains(1));
assert!(domain1.contains(2));
assert!(!domain1.contains(3));
assert!(domain1.contains(4));
assert!(domain1.contains(5));
}
#[test]
fn test_is_subset_of() {
let mut domain1 = BitSetDomain::new(1, 5);
domain1.remove(1);
domain1.remove(3);
let domain2 = BitSetDomain::new(1, 5);
let mut domain3 = BitSetDomain::new(1, 5);
domain3.remove(1);
domain3.remove(3);
domain3.remove(5);
assert!(domain3.is_subset_of(&domain1)); assert!(domain3.is_subset_of(&domain2)); assert!(!domain2.is_subset_of(&domain3));
let domain4 = BitSetDomain::new(2, 6);
assert!(!domain3.is_subset_of(&domain4)); }
#[test]
fn test_iterator() {
let domain = BitSetDomain::new_from_values(vec![1, 3, 5, 7]);
let values: Vec<i32> = domain.iter().collect();
assert_eq!(values, vec![1, 3, 5, 7]);
let values2: Vec<i32> = (&domain).into_iter().collect();
assert_eq!(values2, vec![1, 3, 5, 7]);
}
#[test]
fn test_display() {
let mut domain = BitSetDomain::new(1, 5);
assert_eq!(format!("{}", domain), "[1,2,3,4,5|]");
domain.remove(3);
let display = format!("{}", domain);
assert!(display.contains("1"));
assert!(display.contains("2"));
assert!(display.contains("4"));
assert!(display.contains("5"));
domain.remove_all();
assert_eq!(format!("{}", domain), "[|]");
}
#[test]
fn test_backtracking() {
let mut domain = BitSetDomain::new(1, 5);
let initial_state = domain.save_state();
domain.remove(2);
domain.remove(4);
assert_eq!(domain.size(), 3);
let intermediate_state = domain.save_state();
domain.remove_all_but(3);
assert!(domain.is_fixed());
assert_eq!(domain.fixed_value(), Some(3));
domain.restore_state(&intermediate_state);
assert_eq!(domain.size(), 3);
assert!(domain.contains(1));
assert!(!domain.contains(2));
assert!(domain.contains(3));
assert!(!domain.contains(4));
assert!(domain.contains(5));
domain.restore_state(&initial_state);
assert_eq!(domain.size(), 5);
for i in 1..=5 {
assert!(domain.contains(i));
}
}
#[test]
fn test_sudoku_domain() {
let mut domain = BitSetDomain::new(1, 9);
assert_eq!(domain.universe_size(), 9);
domain.remove(1);
domain.remove(5);
domain.remove(9);
assert_eq!(domain.size(), 6);
assert_eq!(domain.min(), Some(2));
assert_eq!(domain.max(), Some(8));
let values: Vec<i32> = domain.iter().collect();
assert_eq!(values, vec![2, 3, 4, 6, 7, 8]);
}
#[test]
fn test_edge_cases() {
let domain = BitSetDomain::new(42, 42);
assert_eq!(domain.size(), 1);
assert!(domain.is_fixed());
assert_eq!(domain.fixed_value(), Some(42));
assert_eq!(domain.min(), Some(42));
assert_eq!(domain.max(), Some(42));
let domain = BitSetDomain::new(0, 127);
assert_eq!(domain.universe_size(), 128);
assert_eq!(domain.size(), 128);
}
#[test]
fn test_too_large_domain() {
let domain = BitSetDomain::new(0, 128); assert!(domain.is_invalid(), "Domain with 129 values should be invalid");
assert_eq!(domain.size(), 0);
assert!(!domain.contains(64));
assert!(domain.is_empty());
}
#[test]
fn test_invalid_domain_behavior() {
let mut invalid = BitSetDomain::new_invalid();
assert!(invalid.is_invalid());
assert_eq!(invalid.size(), 0);
assert!(invalid.is_empty());
assert!(!invalid.contains(0));
assert!(!invalid.contains(100));
assert!(!invalid.insert(5));
assert!(!invalid.remove(5));
assert!(invalid.is_empty());
let invalid_new = BitSetDomain::new(0, 200); assert!(invalid_new.is_invalid());
let invalid_empty = BitSetDomain::new_empty(0, 200); assert!(invalid_empty.is_invalid());
let invalid_from_values = BitSetDomain::new_from_values((0..150).collect()); assert!(invalid_from_values.is_invalid());
let valid = BitSetDomain::new(0, 127); assert!(!valid.is_invalid());
assert_eq!(valid.size(), 128);
}
#[test]
fn test_safe_constructors() {
let domain = BitSetDomain::try_new(1, 5).expect("Should create valid domain");
assert_eq!(domain.size(), 5);
assert!(domain.contains(1));
assert!(domain.contains(5));
let domain = BitSetDomain::try_new_empty(1, 5).expect("Should create valid empty domain");
assert_eq!(domain.size(), 0);
let domain = BitSetDomain::try_new_from_values(vec![2, 4, 6]).expect("Should create valid domain from values");
assert_eq!(domain.size(), 3);
assert!(domain.contains(2));
assert!(domain.contains(4));
assert!(domain.contains(6));
let domain = BitSetDomain::try_new(0, 127).expect("Should create domain with max size");
assert_eq!(domain.size(), 128);
let result = BitSetDomain::try_new(0, 128); assert!(result.is_err());
assert!(result.unwrap_err().contains("BitSetDomain supports at most 128 values"));
let result = BitSetDomain::try_new_empty(0, 128); assert!(result.is_err());
let large_values: Vec<i32> = (0..129).collect();
let result = BitSetDomain::try_new_from_values(large_values);
assert!(result.is_err());
let domain = BitSetDomain::try_new_from_values(vec![]).expect("Empty values should work");
assert_eq!(domain.size(), 0);
}
#[test]
fn test_performance_characteristics() {
let mut domain = BitSetDomain::new(1, 20);
for i in 1..=20 {
if i % 2 == 0 {
domain.remove(i);
}
}
assert_eq!(domain.size(), 10);
for i in 1..=20 {
let expected = i % 2 == 1;
assert_eq!(domain.contains(i), expected);
}
let values: Vec<i32> = domain.iter().collect();
assert_eq!(values.len(), 10);
}
#[test]
fn test_u128_upgrade_comprehensive() {
let mut small_domain = BitSetDomain::new(1, 9);
assert_eq!(small_domain.size(), 9);
assert_eq!(small_domain.to_vec(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
assert!(small_domain.remove(5));
assert!(!small_domain.contains(5));
assert_eq!(small_domain.size(), 8);
let mut medium_domain = BitSetDomain::new(1, 80);
assert_eq!(medium_domain.size(), 80);
assert!(medium_domain.remove(70));
assert!(medium_domain.remove(75));
assert!(!medium_domain.contains(70));
assert!(!medium_domain.contains(75));
assert_eq!(medium_domain.size(), 78);
let mut large_domain = BitSetDomain::new(1, 120);
assert_eq!(large_domain.size(), 120);
assert!(large_domain.contains(100));
assert!(large_domain.contains(120));
assert!(large_domain.remove(100));
assert!(large_domain.remove(120));
assert!(!large_domain.contains(100));
assert!(!large_domain.contains(120));
assert_eq!(large_domain.size(), 118);
let mask = large_domain.get_mask();
assert_ne!(mask, 0u128);
let mut domain1 = BitSetDomain::new(1, 100);
let mut domain2 = BitSetDomain::new(1, 100);
domain2.remove(50);
assert!(domain1.intersect_with(&domain2).is_ok());
assert!(!domain1.contains(50));
assert_eq!(domain1.size(), 99);
}
#[test]
fn test_bit_operations_u128() {
let mut domain = BitSetDomain::new(0, 127);
assert!(domain.contains(100));
assert!(domain.contains(127));
domain.remove(100);
domain.remove(127);
assert!(!domain.contains(100));
assert!(!domain.contains(127));
assert_eq!(domain.size(), 126);
let mask = domain.get_mask();
assert_eq!(mask.count_ones() as usize, 126);
domain.remove_above(100);
assert!(!domain.contains(101));
assert!(!domain.contains(126));
assert!(domain.contains(99));
domain.remove_below(50);
assert!(!domain.contains(49));
assert!(!domain.contains(1));
assert!(domain.contains(50));
let values: Vec<i32> = domain.iter().collect();
assert_eq!(values, (50..=99).filter(|&x| x != 100).collect::<Vec<_>>());
}
#[test]
fn test_gac_mask_operations_u128() {
let domain1 = BitSetDomain::new(1, 80);
let domain2 = BitSetDomain::new(1, 80);
let union_mask = domain1.union_mask(&domain2).unwrap();
assert_eq!(union_mask.count_ones() as usize, 80);
let mut domain3 = BitSetDomain::new(1, 80);
let remove_mask = (1u128 << 10) | (1u128 << 20) | (1u128 << 70); assert!(domain3.remove_by_mask(remove_mask));
assert!(!domain3.contains(11));
assert!(!domain3.contains(21));
assert!(!domain3.contains(71));
assert_eq!(domain3.size(), 77);
}
#[test]
fn test_sudoku_specific_operations() {
let mut domain = BitSetDomain::new(1, 9);
domain.remove(5); assert_eq!(domain.size(), 8);
let mut other_domain = BitSetDomain::new(1, 9);
other_domain.remove(3);
other_domain.remove(7);
assert!(domain.intersect_with(&other_domain).is_ok());
assert!(!domain.contains(3));
assert!(!domain.contains(5));
assert!(!domain.contains(7));
assert_eq!(domain.size(), 6);
let values: Vec<i32> = domain.iter().collect();
assert_eq!(values, vec![1, 2, 4, 6, 8, 9]);
domain.remove_all_but(4);
assert!(domain.is_fixed());
assert_eq!(domain.fixed_value(), Some(4));
assert_eq!(domain.size(), 1);
}
}